Oulipo
Problem's link: http://poj.org/problem? Id = 3461
Mean:
We will give you a mode string P and a parent string s, so that you can count the number of occurrences of the P string in the S string.
Analyze:
The first thing I thought of was using KMP, which was written in KMP, 93 ms, which was fast. I wrote it again using an AC automatic machine (purely for entertainment). I never expected it to have timed out. Is it my wrong posture?
Later, let's look at other people's useful string hash writing. I heard that string hash is much more powerful than AC ry in some problems, so I wrote it again using string hash, which is really good, over 30 lines of code, and fast, 173 Ms. It is really a good thing to do with string hash. After hearing that string hash is proficient, there will be no other AC automatic machines or Suffix Arrays to solve many problems.
After the unsigned long is learned in the string hash, it will automatically modulo 2 ^ 64. The hash tool saves the manual modulo.
Time Complexity:O (N * m)
Source code:
String hash code:
#include<stdio.h>#include<string.h>#define ULL unsigned long longint seed=100;char s1[10005],s2[1000005];int main(){ int t; scanf("%d",&t); while(t--) { scanf("%s%s",s1,s2); int len1=strlen(s1),len2=strlen(s2); ULL a1=0,a2=0,l1=1; for(int i=0;i<len1;++i) { a1=a1*seed+(s1[i]-‘A‘+1); l1*=seed; } for(int i=0;i<len1;++i) { a2=a2*seed+(s2[i]-‘A‘+1); } int ans=0; if(a1==a2) ans++; for(int i=len1;i<len2;++i) { a2=a2*seed+(s2[i]-‘A‘+1)-l1*(s2[i-len1]-‘A‘+1); if(a2==a1) ans++; } printf("%d\n",ans); } return 0;}
KMP code:
// Memory Time// 1347K 0MS// by : Snarl_jsb// 2014-10-04-11.53#include<algorithm>#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<vector>#include<queue>#include<stack>#include<map>#include<string>#include<climits>#include<cmath>#define N 1000010#define LL long longusing namespace std;char s1[10005],s2[1000005];vector<int> next;void GetNext(char s[]){ int len=strlen(s),k=0; next.clear(); next.push_back(0); for(int i=1;i<len;++i) { while(k!=0&&s[i]!=s[k]) k=next[k-1]; if(s[i]==s[k]) k++; next.push_back(k); }}int KMP(char s1[],char s2[]){ int l1=strlen(s1),l2=strlen(s2); int k=0,ans=0;; for(int i=0;i<l2;++i) { while(k!=0&&s2[i]!=s1[k]) k=next[k-1]; if(s2[i]==s1[k]) k++; if(k==l1) { ans++; k=next[k-1]; } } return ans;}int main(){ int t; scanf("%d",&t); while(t--) { scanf("%s%s",s1,s2); int len1=strlen(s1),len2=strlen(s2); GetNext(s1); printf("%d\n",KMP(s1,s2)); } return 0;}
AC automatic machine timeout code (Qaq ):
// Memory time // 1347 K 0 Ms //: snarl_jsb // 2014-09-30-11.01 # include <algorithm> # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <string> # include <climits> # include <cmath> # define ll long longusing namespace STD; const int n = 1001000; char STR [N]; struct node {node * Next [30]; // each node corresponds to the pointer node * fail with 30 letters; // mismatched pointer int Count; // node () // constructor initialization {for (INT I = 0; I <30; I ++) next [I] = NULL; Count = 0; fail = NULL ;}} * Q [N]; node * root; int head, tail; void insert (char * Str) // insert a word. it is equivalent to building a trie tree {node * P = root; int I = 0, index; while (STR [I]) {Index = STR [I]-65; // convert it to a relative number to save if (p-> next [Index] = NULL) // The letter has not been inserted with p-> next [Index] = new node (); // apply for a node P = p-> next [Index] for the letter; // move it to the next I ++;} p-> count ++; // record the node's Total number of times of insertion of Words} void build_ac_automation (node * root) // BFS creates a fail pointer {root-> fail = NULL; Q [tail ++] = root; while (Head <tail) {node * temp = Q [head ++]; node * P = NULL; For (INT I = 0; I <30; I ++) {If (temp-> next [I]! = NULL) {If (temp = root) temp-> next [I]-> fail = root; else {P = temp-> fail; while (P! = NULL) {If (p-> next [I]! = NULL) {temp-> next [I]-> fail = p-> next [I]; break;} p = p-> fail ;} if (P = NULL) temp-> next [I]-> fail = root;} Q [tail ++] = temp-> next [I] ;}} int Total = 0; int query (node * root) // match + statistics {int I = 0, CNT = 0, index; node * P = root; int idx = 0; while (STR [I]) {Index = STR [I]-65; while (p-> next [Index] = NULL & P! = Root) // The prefix is the same, so no matter which pointer goes to the node where count is not 0, then the words represented by this node match successfully. P = p-> fail; // if the word is not matched, the p Pointer Points to P-> fail. (equivalent to the next array of KMP) P = p-> next [Index]; // because the current location is the parent node, so you need to move down a position if (P = NULL) P = root; // If the match fails, move to root and start matching node * temp = P again; // while (temp! = Root & temp-> count! =-1) // statistics -- if the match is successful, count> 1 indicates the number of words that the node represents; otherwise, the node does not have the word {If (temp-> count> 0) {CNT ++; // count the number of times the word appears} // temp-> COUNT =-1; // mark it as-1, indicating that the word has been added to CNT. You do not need to count temp => fail again next time; // determine the matching condition on the entire chain} I ++;} return CNT;} int main () {int t; CIN> T; while (t --) {head = tail = 0; root = new node (); scanf ("% s", STR); insert (STR); build_ac_automation (Root ); scanf ("% s", STR); // query (Root); printf ("% d \ n", query (Root);} return 0 ;}
String hash-simple character matching --- poj 3461