字符串

这里是字符串的主页


  1. KMP

     //s为文本串,t为待匹配串
     //下标从0开始
     const int MAXM = 2e3 + 5;
     char s[MAXM], t[MAXM];
     int nxt[MAXM], n, m;
    
     void getNext(char t[])
     {
         int len = strlen(t);
         nxt[0] = -1;
         int i = 0, j = -1;
         while(i < len) {
             if(j == -1 || t[i] == t[j])
                 nxt[++i] = ++j;
             else j = nxt[j];
         }
     }
    
     vector<int> pos;
     void kmp(char s[], char t[])
     {
         int n = strlen(s);
         int m = strlen(t);
         for(int i = 0, j = 0; i < n; ++i)
         {
             if(j < n && s[i] == t[j])
             {
                 ++j;
             }
             else
             {
                 while(j > 0)
                 {
                     j = nxt[j];
                     if(s[i] == t[j])
                     {
                         ++j;
                         break;
                     }
                 }
             }
             if(j == m)
             {
                 pos.push_back(i - m + 1);
             }
         }
     }
    


  2. 最小(最大)表示法

     string s;
    
     int smallest(bool isSmall)//返回最小/最大表示法的起始下标
     {
         int N = s.size();
         s += s;
         int i = 0, p = 1;
         while(i < N && p < N)
         {
             int k = 0;
             while(s[i + k] == s[p + k]) ++k;
             if(k >= N) break;
             if(isSmall)
             {
                 if(s[i + k] > s[p + k]) i = max(i + k + 1, p + 1);
                 else p = max(p + k + 1, i + 1);
             }
             else
             {
                 if(s[i + k] < s[p + k]) i = max(i + k + 1, p + 1);
                 else p = max(p + k + 1, i + 1);
             }
         }
         return min(i, p);
     }
    


  3. 最长回文子串

     char s[MAXN], ma[MAXN * 2];
     int len[4 * MAXN], n;//n = strlen(s) 初始的字符串长度
    
     void Manacher()
     {
         int l = 0;
         ma[l++] = '$';
         ma[l++] = '#';
         for(int i = 0; i < n; ++i)
         {
             ma[l++] = s[i];
             ma[l++] = '#';
         }
         ma[l] = 0;
         int mx = 0, id = 0;
         for(int i = 0; i < l; ++i)
         {
             len[i] = mx > i ? min(len[2 * id - i], mx - i) : 1;
             while(ma[i + len[i]] == ma[i - len[i]]) len[i]++;
             if(i + len[i] > mx)
             {
                 mx = i + len[i];
                 id = i;
             }
         }
     }
    


  4. Trie树
    单独考一个的不多。。而且也应该比较好写吧。。

  5. AC自动机
     const int MAXNODE = 40;
     struct Trie
     {
         int next[MAXNODE][26], fail[MAXNODE], end[MAXNODE];
         int root, L;
         int newnode()
         {
             for(int i = 0; i < 26; ++i)
                 next[L][i] = -1;
             end[L++] = 0;
             return L - 1;
         }
         void init()
         {
             L = 0;
             root = newnode();
         }
         void insert(char buf[])
         {
             int len = strlen(buf);
             int now = root;
             for(int i = 0; i < len; ++i)
             {
                 if(next[now][buf[i] - 'a'] == -1)
                     next[now][buf[i] - 'a'] = newnode();
                 now = next[now][buf[i] - 'a'];
             }
             ++end[now];
         }
         void build()
         {
             queue<int> q;
             fail[root] = root;
             for(int i = 0; i < 26; ++i)
                 if(next[root][i] == -1)
                     next[root][i] = root;
                 else
                 {
                     fail[next[root][i]] = root;
                     q.push(next[root][i]);
                 }
             while(!q.empty())
             {
                 int now = q.front();
                 q.pop();
                 if(end[fail[now]]) end[now] = 1;// TODO 貌似并不是都需要这句话?
                 for(int i = 0;i < 26; ++i)
                     if(next[now][i] == -1)
                         next[now][i] = next[fail[now]][i];
                     else
                     {
                         fail[next[now][i]] = next[fail[now]][i];
                         q.push(next[now][i]);
                     }
             }
         }
         int query(char buf[])
         {
             int len = strlen(buf);
             int now = root;
             int res = 0;
             for(int i = 0; i < len; ++i)
             {
                 now = next[now][buf[i] - 'a'];
                 int temp = now;
                 while(temp != root)
                 {
                     res += end[temp];
                     end[temp] = 0;
                     temp = fail[temp];
                 }
             }
             return res;
         }
     } ac;
    

  6. 后缀数组

     const int MAXN = 1e5 + 5;
     const int MAXL = 2e5 + 5;
    
     void radixSort(int *str, int *a, int *b, int n, int m)
     {
         static int count[MAXL];
         memset(count, 0, sizeof(count));
         for(int i = 0; i < n; ++i) ++count[str[a[i]]];
         for(int i = 1; i <= m; ++i) count[i] += count[i - 1];
         for(int i = n - 1; i >= 0; --i) b[--count[str[a[i]]]] = a[i];
     }
    
     void getSA(int *str, int *sa, int n, int m)
     {
         static int rank[MAXL], a[MAXL], b[MAXL];
         for(int i = 0; i < n; ++i) rank[i] = i;
         radixSort(str, rank, sa, n, m);
    
         rank[sa[0]] = 0;
         for(int i = 1; i < n; ++i)
             rank[sa[i]] = rank[sa[i - 1]] + (str[sa[i]] != str[sa[i - 1]]);
         for(int i = 0; (1 << i) < n; ++i)
         {
             for(int j = 0; j < n; ++j)
             {
                 a[j] = rank[j] + 1;
                 b[j] = j + (1 << i) >= n ? 0 : rank[j + (1 << i)] + 1;
                 sa[j] = j;
             }
             radixSort(b, sa, rank, n, n);
             radixSort(a, rank, sa, n, n);
             rank[sa[0]] = 0;
             for(int j = 1; j < n; ++j)
             {
                 rank[sa[j]] = rank[sa[j - 1]] +
                             (a[sa[j - 1]] != a[sa[j]] || b[sa[j - 1]] != b[sa[j]]);
             }
         }
     }
    
     int s[MAXN], sa[MAXN], h[MAXN];
     char buf[MAXN];
     int rnk[MAXN];
    
     void calcHeight(int *str, int *sa, int *h, int n)
     {
         int k = 0;
         h[0] = 0;
         for(int i = 1; i <= n; ++i) rnk[sa[i]] = i;
         for(int i = 0; i < n; ++i)
         {
             k = k == 0 ? 0 : k - 1;
             if(rnk[i] != 0)
                 while(str[i + k] == str[sa[rnk[i] - 1] + k]) ++k;
             h[rnk[i]] = k;
         }
     }
    
     int main()
     {
         scanf("%s", buf);
         int len = strlen(buf);
         for(int i = 0; i < len; ++i) s[i] = buf[i] - 'a' + 1;
         s[len] = 0;
         getSA(s, sa, len + 1, 30);//仅小写字母情况下
         calcHeight(s, sa, h, len);
     }