Guest User

Untitled

a guest
Apr 21st, 2023
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.65 KB | None | 0 0
  1. #include<algorithm>
  2. #include<cassert>
  3. #include<cctype>
  4. #include<cmath>
  5. #include<cstdio>
  6. #include<cstring>
  7. #include<functional>
  8. #include<iomanip>
  9. #include<iostream>
  10. #include<map>
  11. #include<queue>
  12. #include<set>
  13. #include<sstream>
  14. #include<stack>
  15. #include<string>
  16. #include<utility>
  17. #include<vector>
  18. using namespace std;
  19.  
  20. #define ll long long
  21. //#define int ll
  22.  
  23. const int inf=0x3f3f3f3f;
  24. const ll INF=0x3f3f3f3f3f3f3f3f;
  25.  
  26. const int MAXLEN = 2000005;
  27. struct SAIS
  28. {
  29.     // 后缀类型
  30. #define L_TYPE 0
  31. #define S_TYPE 1
  32.    
  33.     int st[MAXLEN];
  34.     int rl[MAXLEN],rk[MAXLEN],lcp[MAXLEN];
  35.     int n;
  36.    
  37.     void init(const char*s,const int&_n)
  38.     {
  39.         n = _n;
  40.         for (int i=1;i<=n;++i) st[i] = s[i-1];
  41.         // st中的字符必须调成正数!!!!!!!!!!!!!!
  42.     }
  43.    
  44.     // 判断一个字符是否为LMS字符
  45.     inline bool is_lms_char(int *type, int x) {
  46.         return x > 1 && type[x] == S_TYPE && type[x - 1] == L_TYPE;
  47.     }
  48.    
  49.     // 判断两个LMS子串是否相同
  50.     inline bool equal_substring(int *S, int x, int y, int *type) {
  51.         do {
  52.             if (S[x] != S[y])
  53.                 return false;
  54.             x++, y++;
  55.         } while (!is_lms_char(type, x) && !is_lms_char(type, y));
  56.        
  57.         return S[x] == S[y] && type[x] == type[y];
  58.     }
  59.    
  60.     // 诱导排序(从*型诱导到L型、从L型诱导到S型)
  61.     // 调用之前应将*型按要求放入SA中
  62.     inline void induced_sort(int *S, int *SA, int *type, int *bucket, int *lbucket,
  63.                              int *sbucket, int nn, int SIGMA) {
  64.         for (int i = 1; i <= nn; i++)
  65.             if (SA[i] > 1 && type[SA[i] - 1] == L_TYPE)
  66.                 SA[lbucket[S[SA[i] - 1]]++] = SA[i] - 1;
  67.         for (int i = 0; i <= SIGMA; i++)  // Reset S-type bucket
  68.             sbucket[i] = bucket[i];
  69.         for (int i = nn; i >= 1; i--)
  70.             if (SA[i] > 1 && type[SA[i] - 1] == S_TYPE)
  71.                 SA[sbucket[S[SA[i] - 1]]--] = SA[i] - 1;
  72.     }
  73.    
  74.     // SA-IS主体
  75.     // S是输入字符串,length是字符串的长度, SIGMA是字符集的大小
  76.     int *sais(int *S, int length, int SIGMA) {
  77.         int nn = length;
  78.         assert(S[nn]==0);
  79.         int *type = new int[nn + 5];  // 后缀类型
  80.         int *position = new int[nn + 5];  // 记录LMS子串的起始位置
  81.         int *name = new int[nn + 5];  // 记录每个LMS子串的新名称
  82.         int *SA = new int[nn + 5];  // SA数组
  83.         int *bucket = new int[SIGMA + 5];  // 每个字符的桶
  84.         int *lbucket = new int[SIGMA + 5];  // 每个字符的L型桶的起始位置
  85.         int *sbucket = new int[SIGMA + 5];  // 每个字符的S型桶的起始位置
  86.        
  87.         // 初始化每个桶
  88.         memset(bucket, 0, sizeof(int) * (SIGMA + 5));
  89.         for (int i = 1; i <= nn; i++)
  90.             bucket[S[i]]++;
  91.         for (int i = 0; i <= SIGMA; i++) {
  92.             if (i==0)
  93.             {
  94.                 bucket[i] = bucket[i];
  95.                 lbucket[i] = 1;
  96.             }else
  97.             {
  98.                 bucket[i] += bucket[i - 1];
  99.                 lbucket[i] = bucket[i - 1] + 1;
  100.             }
  101.             sbucket[i] = bucket[i];
  102.         }
  103.        
  104.         // 确定后缀类型(利用引理2.1)
  105.         type[nn] = S_TYPE;
  106.         for (int i = nn - 1; i >= 1; i--) {
  107.             if (S[i] < S[i + 1])
  108.                 type[i] = S_TYPE;
  109.             else if (S[i] > S[i + 1])
  110.                 type[i] = L_TYPE;
  111.             else
  112.                 type[i] = type[i + 1];
  113.         }
  114.         // 寻找每个LMS子串
  115.         int cnt = 0;
  116.         for (int i = 1; i <= nn; i++)
  117.             if (is_lms_char(type,i))
  118.                 position[++cnt] = i;
  119.         // 对LMS子串进行排序
  120.         fill(SA, SA + nn + 3, -1);
  121.         for (int i = 1; i <= cnt; i++)
  122.             SA[sbucket[S[position[i]]]--] = position[i];
  123.         induced_sort(S, SA, type, bucket, lbucket, sbucket, nn, SIGMA);
  124.        
  125.         // 为每个LMS子串命名
  126.         fill(name, name + nn + 3, -1);
  127.         int lastx = -1, namecnt = 1;  // 上一次处理的LMS子串与名称的计数
  128.         bool flag = false;  // 这里顺便记录是否有重复的字符
  129.         for (int i = 2; i <= nn; i++) {
  130.             int x = SA[i];
  131.            
  132.             if (is_lms_char(type, x)) {
  133.                 if (lastx >= 0 && !equal_substring(S, x, lastx, type))
  134.                     namecnt++;
  135.                 // 因为只有相同的LMS子串才会有同样的名称
  136.                 if (lastx >= 0 && namecnt == name[lastx])
  137.                     flag = true;
  138.                
  139.                 name[x] = namecnt;
  140.                 lastx = x;
  141.             }
  142.         }  // for
  143.         name[nn] = 0;
  144.        
  145.         // 生成S1
  146.         int *S1 = new int[cnt+5];
  147.         int pos = 0;
  148.         for (int i = 1; i <= nn; i++)
  149.             if (name[i] >= 0)
  150.                 S1[++pos] = name[i];
  151.         int *SA1;
  152.         if (!flag) {
  153.             // 直接计算SA1
  154.             SA1 = new int[cnt + 5];
  155.            
  156.             for (int i = 1; i <= cnt; i++)
  157.                 SA1[S1[i]+1] = i;
  158.         } else
  159.             SA1 = sais(S1, cnt, namecnt);  // 递归计算SA1
  160.        
  161.         // 从SA1诱导到SA
  162.         for (int i = 0; i <= SIGMA; i++) {
  163.             if (i==0)
  164.                 lbucket[i] = 1;
  165.             else
  166.                 lbucket[i] = bucket[i - 1] + 1;
  167.             sbucket[i] = bucket[i];
  168.         }
  169.         fill(SA, SA + nn + 3, -1);
  170.         for (int i = cnt; i >= 1; i--)  // 这里是逆序扫描SA1,因为SA中S型桶是倒序的
  171.             SA[sbucket[S[position[SA1[i]]]]--] = position[SA1[i]];
  172.         induced_sort(S, SA, type, bucket, lbucket, sbucket, nn, SIGMA);
  173.        
  174.         delete[] S1;
  175.         delete[] SA1;
  176.         delete[] bucket;
  177.         delete[] lbucket;
  178.         delete[] sbucket;
  179.         delete[] position;
  180.         delete[] type;
  181.         delete[] name;
  182.         // 后缀数组计算完毕
  183.         return SA;
  184.     }
  185.    
  186.     void build()
  187.     {
  188.         st[0]=st[n+2]=-1;
  189.         st[n+1]=0;
  190.         int SIGMA = 0;
  191.         for (int i=1;i<=n;++i) SIGMA = max(SIGMA,st[i]);
  192.         int * sa = sais(st,n+1,SIGMA);
  193.         for (int i=2;i<=n+1;++i) rk[sa[i]]=i-1;
  194.         delete[] sa;
  195.         for (int i=1;i<=n;++i) rl[rk[i]]=i;
  196.         for (int i=1,len=0;i<=n;++i)
  197.         {
  198.             if (len) --len;
  199.             while (i+len<=n && rl[rk[i]-1]+len<=n && st[i+len]==st[rl[rk[i]-1]+len]) ++len;
  200.             lcp[rk[i]]=len;
  201.         }
  202.     }
  203.  
  204. #undef L_TYPE
  205. #undef R_TYPE
  206. }sa;
  207. char s[1000005];
  208.  
  209. void solve()
  210. {
  211.     scanf("%s",s+1);
  212.     int n=strlen(s+1);
  213.     sa.init(s+1,n);
  214.     sa.build();
  215.     ll ans=0;
  216.     for(int i=1;i<=n;i++)
  217.         ans+=n-sa.rl[i]+1-sa.lcp[i];
  218.     printf("%lld\n",ans);
  219. }
  220.  
  221. signed main()
  222. {
  223. //  ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
  224.  
  225.  
  226.  
  227.     int _;scanf("%d",&_);while(_--)
  228.         solve();
  229.     return 0;
  230. }
Advertisement
Add Comment
Please, Sign In to add comment