根据height数组的性质分组计算。
#include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include <string> #include <queue> #include <stack> #include <bitset> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<1 #define mem(a) memset(a, 0, sizeof(a)) #define rson m+1, r, rt<<1|1 #define mem1(a) memset(a, -1, sizeof(a)) #define mem2(a) memset(a, 0x3f, sizeof(a)) #define rep(i, n, a) for(int i = a; i<n; i++) #define fi first #define se second typedef pair<int, int> pll; const double PI = acos(-1.0); const double eps = 1e-8; const int mod = 1e9+7; const int inf = 1061109567; const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; const int maxn = 2e4+5; int sa[maxn]; int t1[maxn],t2[maxn],c[maxn], a[maxn]; int rankk[maxn],height[maxn], ans; void build_sa(int s[],int n,int m) { int i,j,p,*x=t1,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=s[i]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(j=1;j<=n;j<<=1) { p=0; for(i=n-j;i<n;i++)y[p++]=i; for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[y[i]]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++; if(p>=n)break; m=p; } } void getHeight(int s[],int n) { int i,j,k=0; for(i=0;i<=n;i++)rankk[sa[i]]=i; for(i=0;i<n;i++) { if(k)k--; j=sa[rankk[i]-1]; while(s[i+k]==s[j+k])k++; height[rankk[i]]=k; } } int cal(int x, int n) { int minn = sa[1], maxx = sa[1]; int flag = 0; for(int i = 2; i<=n; i++) { if(height[i]<x) { if(maxx-minn>=x) ans++; maxx = minn = sa[i]; flag = 1; } else { maxx = max(maxx, sa[i]); minn = min(minn, sa[i]); } } if(maxx-minn>=x) ans++, flag = 1; return flag; } int main() { string s; while(cin>>s) { if(s[0] == '#') break; ans = 0; for(int i = 0; i<s.size(); i++) a[i] = s[i]-'a'+1; a[s.size()] = 0; build_sa(a, s.size()+1, 30); getHeight(a, s.size()); for(int i = 1; i<=(s.size()+1)/2; i++) { if(!cal(i, s.size())) break; } cout<<ans<<endl; } return 0; }