zoj 3228 Searching the String
题意:
给一个1e5长只有小写字母的串,1e5个询问,问某个串在可以重叠或者不可以重叠的条件下最大匹配数。
解法:
最开始的时候在Trie的每个节点把所有出现的单词编号全塞到vector里,结果TLE到死。其实如果在插入的时候,以同一个节点作为终止节点的只有那一个。。所以对一个串只插入一次就行,然后自动机匹配的时候分别统计可以重叠和不可以重叠的匹配数。
可以重叠的匹配只要在自动机上跑就行,对于不可以重叠的,记录一下上次匹配的位置,然后判断一下是否满足条件就行。。
字符串判重的时候我写了个双重hash。。。
1 #include<cstdio> 2 #include<map> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 const int N = (int)1e6+10; 8 const int M = (int)1e5+5; 9 struct node{ 10 node *ch[26],*fail; 11 int index,deep; 12 void clear(){ 13 for(int i = 0;i < 26;i++)ch[i] = NULL; 14 fail = NULL; 15 index = 0; 16 deep = 0; 17 } 18 }; 19 node stk[N]; 20 bool type[M]; 21 int last[M],vis[M][2]; 22 struct Trie{ 23 node *root; 24 int top; 25 node* new_node(){ 26 node *p = &stk[top++]; 27 p -> clear(); 28 return p; 29 } 30 void init(){ 31 top = 0; 32 root = new_node(); 33 } 34 void insert(char *s,int index){ 35 node *p = root; 36 for(int i = 0;s[i];i++){ 37 int id = s[i] - 'a'; 38 if(p -> ch[id] == NULL) 39 p -> ch[id] = new_node(); 40 p = p -> ch[id]; 41 p -> deep = i + 1; 42 } 43 p -> index = index; 44 } 45 void build(){ 46 queue<node*> Q; 47 root -> fail = NULL; 48 for(int i = 0;i < 26;i++) 49 if(root -> ch[i] == NULL) 50 root -> ch[i] = root; 51 else{ 52 Q.push(root -> ch[i]); 53 root -> ch[i] -> fail = root; 54 } 55 while(!Q.empty()){ 56 node *p = Q.front();Q.pop(); 57 for(int i = 0;i < 26;i++) 58 if(p -> ch[i] == NULL) 59 p -> ch[i] = p -> fail -> ch[i]; 60 else{ 61 Q.push(p -> ch[i]); 62 p -> ch[i] -> fail = p -> fail -> ch[i]; 63 } 64 } 65 } 66 void solve(char *s){ 67 node *p = root; 68 for(int i = 0;s[i];i++){ 69 int id = s[i] - 'a'; 70 p = p -> ch[id]; 71 node *u = p; 72 while(u != root){ 73 int cur = u -> index; 74 if(cur){ 75 vis[cur][0]++; 76 if(last[cur] == -1){ 77 vis[cur][1]++; 78 last[cur] = i; 79 }else if(i - last[cur] >= u->deep){ 80 vis[cur][1]++; 81 last[cur] = i; 82 } 83 } 84 u = u -> fail; 85 } 86 } 87 } 88 }; 89 Trie AC; 90 char s[M]; 91 typedef unsigned long long ull; 92 map<pair<ull,ull>,int>Map; 93 int number[M]; 94 inline pair<ull,ull> geths(char *s){ 95 pair<ull,ull> ans(0,0); 96 int len = strlen(s); 97 for(int i = 0;i < len;i++){ 98 ans.first = ans.first * 31 + s[i]; 99 ans.second = ans.second * 131 + s[i]; 100 } 101 return ans; 102 } 103 int main(){ 104 int cas = 1,n; 105 while(~scanf("%s",s)){ 106 scanf("%d",&n); 107 AC.init(); 108 int cnt = 0; 109 Map.clear(); 110 for(int i = 1;i <= n;i++){ 111 char x[10];int flag; 112 scanf("%d%s",&flag,x); 113 type[i] = flag; 114 vis[i][0] = vis[i][1] = 0; 115 last[i] = -1; 116 pair<ull,ull> hs = geths(x); 117 if(!Map.count(hs)){ 118 Map[hs] = ++cnt; 119 AC.insert(x,Map[hs]); 120 } 121 number[i] = Map[hs]; 122 } 123 AC.build(); 124 AC.solve(s); 125 printf("Case %d\n",cas++); 126 for(int i = 1;i <= n;i++) 127 printf("%d\n",vis[number[i]][type[i]]); 128 puts(""); 129 } 130 return 0; 131 }