1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
| #include<bits/stdc++.h> #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,l,r) for(int i=l;i>=r;i--) #define link(x) for(edge*j=h[x];j;j=j->next) #define ll long long #define sqr(x) ((x)*(x)) #define succ(x) (1<<x) #define lowbit(x) (x&(-x)) #define mem(a) memset(a,0,sizeof(a)) using namespace std; const int inf=1e9+9; ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } const int MAXN=3005;
int n,ca; char _s[MAXN]; ll d[MAXN][MAXN],ans; int sa[MAXN],txt[MAXN],t1[MAXN],t2[MAXN],rank1[MAXN],rank2[MAXN],td[MAXN]; bool cmp(int f[],int tt,int ttt,int k){ return f[tt]==f[ttt]&&f[tt+k]==f[ttt+k]; } void Sa(char str[]){ int m=250;int len=strlen(str); int *td=t1;int *rank1=t2; for(int i=0;i<m;i++)txt[i]=0; for(int i=0;i<len;i++)txt[str[i]]++,rank1[i]=str[i]; for(int i=1;i<m;i++)txt[i]+=txt[i-1]; for(int i=len-1;i>=0;i--)sa[--txt[str[i]]]=i; for(int k=1;k<=len;k=k*2){ int p=0; for(int i=len-k;i<len;i++)td[p++]=i; for(int i=0;i<len;i++)if(sa[i]>=k)td[p++]=sa[i]-k; for(int i=0;i<m;i++)txt[i]=0; for(int i=0;i<len;i++)txt[rank1[i]]++; for(int i=1;i<m;i++)txt[i]+=txt[i-1]; for(int i=len-1;i>=0;i--)sa[--txt[rank1[td[i]]]]=td[i]; p=1; swap(rank1,td); rank1[sa[0]]=0; for(int i=1;i<len;i++)rank1[sa[i]]=cmp(td,sa[i],sa[i-1],k)?p-1:p++; if(p>=len)return ; m=p; } }
int h[MAXN],H[MAXN]; void HH(char str[]){ int len=strlen(str); for(int i=0;i<len;i++)rank2[sa[i]]=i; memset(H,0,sizeof(H)); for(int i=0;i<len;i++){ if(rank2[i]==0)continue; int t=sa[rank2[i]-1];int w=i;int k=0; if(i==0||H[i-1]<=1)k=0; else k=H[i-1]-1,t+=k,w+=k; while(t<len&&w<len){ if(str[t]==str[w])k++; else break; t++;w++; } H[i]=k;h[rank2[i]]=k; } }
int dp[MAXN][16],ma[MAXN]; void St(char str[]){ int len=strlen(str); inc(i,2,len)ma[i]=ma[i/2]+1; for(int i=1;i<len;i++)dp[i][0]=h[i]; for(int j=1;j<=15;j++){ for(int i=1;i+(1<<j)<=len;i++){ dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } } }
int Lcp(int l,int r){ if(l>r)swap(l,r); l++; int k=ma[r-l+1]; return min(dp[l][k],dp[r-(1<<k)+1][k]); }
int main(){ while(~scanf("%s",_s)){ if(_s[0]=='-')break; n=strlen(_s);ans=0; _s[n]='$';_s[n+1]='\0'; Sa(_s);HH(_s);St(_s); inc(i,0,n-1)inc(j,0,n-1)d[i][j]=0; inc(j,0,n-1)d[0][j]=1; inc(i,1,n-1){ inc(j,0,i-1){ int t=Lcp(rank2[i],rank2[j]); if(t+j>=i&&i+i-j<n){ (d[i][i+(i-j)]+=d[j][i-1])%=inf; }else{ if(rank2[i]>rank2[j]&&i+t<n) (d[i][i+t]+=d[j][i-1])%=inf; } } inc(j,i+1,n-1)(d[i][j]+=d[i][j-1])%=inf; } inc(i,0,n-1)ans+=d[i][n-1],ans%=inf; printf("Case #%d: There are %lld ways.\n",++ca,ans); } return 0; }
|