字符串数据结构模板

Trie 树

 

字典树,用于存储和查询数量较大的字符串。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define maxn 500010
 5 using namespace std;
 6 char aa[51];
 7 
 8 struct Trie {
 9     int sz;
10     int ch[maxn][26];
11     int val[maxn];
12     Trie() { sz=1; memset(ch[0],0,sizeof(ch[0])); }
13     int idx(char x) {return x-'a';}
14     void insert(char *s) {
15         int n=strlen(s);
16         int u=0;
17         for (int i=0; i<n;i++) {
18             int c=idx(s[i]);
19             if(!ch[u][c]) {
20                 memset(ch[sz],0,sizeof(ch[sz]));
21                 val[sz]=0;
22                 ch[u][c]=sz++;
23             }
24             u=ch[u][c];
25         }
26         val[u]=1;
27     }
28     void check(char *s) {
29         int n=strlen(s);
30         int u=0;
31         for (int i=0;i<n;i++) {
32             int c=idx(s[i]);    
33             if(!ch[u][c]) { cout<<"WRONG\n"; return;}
34             u=ch[u][c];
35         }
36         if(val[u]==1) {cout<<"OK\n"; val[u]++;}
37         else if(val[u]>1) cout<<"REPEAT\n";
38         else cout<<"WRONG\n";
39         return;
40     }
41 }trie;
42 
43 int main() {
44     int n;
45     cin>>n;
46     for (int i=1;i<=n;i++) {
47         scanf("%s", aa);
48         trie.insert(aa);
49     } 
50     cin>>n;
51     for (int i=1;i<=n;i++) {
52         scanf("%s", aa);
53         trie.check(aa);
54     } 
55     return 0;
56 }

例题:洛谷P2580

 

KMP算法

 

支持单个模式串匹配。

思想:用自己匹配自己。核心是next数组。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 using namespace std;
 6 string s1, s2;
 7 int len1, len2;
 8 int next[1001];
 9 
10 void NEXT_init(){
11     for (int i=1;i<len2;i++) {
12         int j=next[i-1];
13         while (j && s2[j]!=s2[i])
14             j=next[j-1];
15         if(s2[i]==s2[j]) j++;
16         next[i]=j;
17     }
18     return ;
19 }
20 
21 void kmp() {
22     int j=0;
23     for (int i=0;i<len1;i++) {
24         while(j && s1[i]!=s2[j])
25             j=next[j-1];
26         if (s1[i]==s2[j]) 
27              j++;
28         if(j==len2) 
29             cout<<i-j+2<<endl;
30     }
31     return ;
32 }
33 
34 int main() {
35     cin>>s1>>s2;
36     len1=s1.length();
37     len2=s2.length();
38     NEXT_init(); 
39     kmp();
40     for (int i=0; i<len2; i++)
41         cout<<next[i]<<" ";
42     return 0;
43 } 

例题:洛谷P3375

 

AC自动机

 

支持多模式串匹配。

思想:Trie树+KMP算法;也可以看做模式串有多个的KMP算法在Trie树上实现。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 using namespace std;
 6 const int maxn 50010
 7 int tot, n;
 8 char s[50];
 9 
10 struct Trie {
11     int sz;
12     int ch[maxn][26];
13     int val[maxn];
14     int f[maxn];
15     Trie() { sz=1; memset(ch[0],0,sizeof(ch[0]));}
16     int idx(char x) { return x-'a'; }
17     
18     void insert(char *s) {
19         int u=0, n=strlen(n);
20         for (int i=0;i<n;i++) {
21             int c=idx(s[i]);
22             if (!ch[u][c]) {
23                 memset(ch[sz],0,sizeof(ch[sz]));
24                 val[sz]=0;
25                 ch[u][c]=sz++;
26             }
27             u=ch[u][c];
28         }
29         val[u]=++tot;
30         return ;
31     }
32     
33     void getFail() {
34         queue <int> q;
35         f[0]=0;
36         for (int i=0; i<26; i++) {
37             int u=ch[0][i];
38             if (u) {
39                 f[u]=0;
40                 q.push(u);
41                 last[u]=0;
42             }
43         }
44         while (!q.empty()) {
45             int r=q.front();
46             q.pop();
47             for (int i=0; i<26; i++) {
48                 int u=ch[r][i];
49                 if (!u) continue;
50                 q.push(u);
51                 int v=f[r];
52                 while(v && !ch[v][i]) v=f[v];
53                 f[u]=ch[v][i];
54                 last[u]=val[f[u]]? f[u]:last[f[u]];
55             }
56         }
57         return ;
58     }
59     
60     void find(char *t) {
61         int n=strlen(t);
62         int j=0;
63         for (int i=0; i<n; i++) {
64             int c=idx(t[i]);
65             while (j && !ch[j][c]) j=f[j];
66             j=ch[j][c];
67             if (val[j]) print(i,j);
68             else if(last[j]) print(i, last[j]); 
69         }
70         return ;
71     }    
72 }trie;
73 
74 
75 void print(int i, int j) {
76     if (j)
77         printf("%d : %d", i, val[j]);
78         print(i, last[j]);
79     return ;
80 } 

 

 

 

 

Manacher

最长回文串的计算。

核心思想是把已经计算过的回文部分“抄过来”。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <string>
 4 using namespace std;
 5 
 6 string a, a1;
 7 int lena, p[100010];
 8 int maxn=0;
 9 
10 int max(int x, int y) {return x>y?x:y;}
11 int min(int x, int y) {return x<y?x:y;}
12 
13 void manacher() {
14     int mx, id;
15     mx=id=0;
16     for (int i=1; i<=lena; i++) {
17         if (mx>i) 
18             p[i]=min(mx-i, p[id*2-i]);
19         while (a[i+p[i]]==a[i-p[i]])
20             p[i]++;
21         if (mx<p[i]) {
22             mx=i+p[i]; id=i;
23         }
24     }
25     for (int i=1; i<=lena; i++) 
26         maxn=max(maxn,p[i]);
27     maxn--;
28     return ;
29 }
30 
31 int main() {
32     cin>>a1;
33     lena=a1.length();
34     a+="$#";
35     for (int i=0; i<lena; i++) {
36         a+=a1[i];
37         a+="#";
38     }
39     lena<<=1;
40     manacher();
41     cout<<maxn;
42     return 0;
43 }

 

字符串Hash

不属于数据结构,但由于也与字符串有关,也放在这里。
使用BKDRHash和APHash
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 unsigned int BKDRHash(char *str) {  
 7     unsigned int seed = 31; // 31 131 1313 13131 131313 etc..  
 8     unsigned int hash = 0;  
 9     while (*str) 
10         hash = hash*seed+(*str++);  
11     return (hash & 0x7FFFFFFF);  
12 }  
13 
14 
15 int APhash1() { 
16   int k(0), len = _str.length();
17   for (int i = 0; i < len; ++i)
18     k = ((_str[i] * (i + 1)) % INF + k) % INF;
19   return k % INF;
20 
21 
22 unsigned int APHash2(char *str) {   //不是很懂的版本,求大佬讲解
23     unsigned int hash = 0;  
24     int i;     
25     for (i=0; *str; i++)   
26         if (!(i&1))
27             hash^=((hash<<7)^(*str++)^(hash>>3));  
28         else    
29             hash^=(~((hash<<11)^(*str++)^(hash>>5)));
30     return (hash&0x7FFFFFFF);  
31 }  

代码出处 BKDRHash & APHash1   APHash2        

 
posted @ 2017-05-04 15:17  3918张佳  阅读(217)  评论(0编辑  收藏  举报