zoukankan      html  css  js  c++  java
  • 字符串数据结构模板

    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
    "; return;}
    34             u=ch[u][c];
    35         }
    36         if(val[u]==1) {cout<<"OK
    "; val[u]++;}
    37         else if(val[u]>1) cout<<"REPEAT
    ";
    38         else cout<<"WRONG
    ";
    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        

     
  • 相关阅读:
    【总结】java 后台文件上传整理
    【很重要】优秀的常用的js库
    封装常用的跨浏览器的事件对象EventUtil
    [H5表单]一些html5表单知识及EventUtil对象完善
    [H5表单]html5自带表单验证体验优化及提示气泡修改
    html5的audio实现高仿微信语音播放效果
    pcre
    tony_nginx_01_如何在linux系统下安装nginx、pcre、zlib、openssl工具
    Linux中编译、安装nginx
    Linux在本地使用yum安装软件
  • 原文地址:https://www.cnblogs.com/zjzj/p/6807290.html
Copyright © 2011-2022 走看看