标签:style blog http color io os ar for sp
题意:给你一个长度为n的字符串环,以位置i开始的顺时针长度为n的环构成的字符串有n个,问其中最小字典序的开始位置,有多种解时,输出起始位置最小的。
分析:
首先可以直接拼接两个长度为n的字符串,设原串为S[0],S[1]...S[n-1]则拼接后就是S‘=S[0],S[1],...S[n-1],S[0],S[1],...S[n-1]。
那么问题中的n个长度为n的字符串中的任意一个,一定存在S‘的某个后缀字符串的前缀与其相等。
我们现在要找最小字典序,则可以直接先求S‘的后缀数组SA,然后:
1、找到第一个SA[i]<n的i
2、可以知道SA[i]一定是字典序最小的后缀,但题目要求有多种解时,输出起始位置最小的。
这个怎么搞呢?其实也蛮简单的,对于所有前n个字符字典序相同的后缀字符串,在SA中一定是相邻的。
所以只要判断LCP[i]是不是大于等于n就可以知道该后缀的长度为n个前缀是不是整体上字典序最小的了。
所以可以这么搞:
while(LCP[i]>=n){
i++;
update(ans);
}
3、输出ans就可以了。其实也可以不update(ans),最后一个满足LCP[i]>=n的i对应的SA[i]一定是答案。
因为前n个字符相同的所有后缀排在后面的一定比排在前面的长
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #include <string> 7 #include <vector> 8 #include <cmath> 9 #include <set> 10 #define maxn 2000010 11 #define maxm 2010 12 #define maxt 110 13 #define INF 0x3f3f3f3f 14 #define mod 1009 15 #define MAX_STATE 2500 16 using namespace std; 17 int n,k; 18 int Rank[maxn]; 19 int temp[maxn]; 20 int LCP[maxn]; 21 int SA[maxn]; 22 //比较(rank[k,i],rank[k,i+k])与(rank[k,j],rank[k,j+k]) 23 bool cmp_sa(int i,int j){ 24 if(Rank[i]!=Rank[j])return Rank[i]<Rank[j]; 25 else{ 26 int ri = i+k<=n?Rank[i+k]:-1; 27 int rj = j+k<=n?Rank[j+k]:-1; 28 return ri<rj; 29 } 30 } 31 void construct_sa(string S,int *sa){ 32 n = S.length(); 33 //长度为1的字符串,Rank直接取字符的编码 34 for(int i=0;i<=n;++i){ 35 sa[i]=i; 36 Rank[i]=i<n?S[i]:-1; 37 } 38 //利用对长度为k的字符串排序计算长度位2k的顺序 39 for(k=1;k<=n;k*=2){//注意这里不是 int k 40 sort(sa,sa+n+1,cmp_sa); 41 //计算新的rank,暂存到temp中 42 temp[sa[0]]=0; 43 //调整rank,相同的字符串的rank时一样的 44 for(int i=1;i<=n;++i){ 45 temp[sa[i]] = temp[sa[i-1]]+ (cmp_sa(sa[i-1],sa[i])?1:0); 46 } 47 //存回rank 48 for(int i=0;i<=n;++i){ 49 Rank[i]=temp[i]; 50 } 51 } 52 } 53 //计算LCP,O(n) 54 void construct_lcp(string S,int *sa,int *lcp){ 55 n = S.length(); 56 for(int i=0;i<=n;++i)Rank[sa[i]]=i; 57 int h=0; 58 lcp[0]=0; 59 for(int i=0;i<n;++i){ 60 //计算字符串从i位置开始的后缀及其在后缀数组前一个的后缀的LCP 61 int j = sa[Rank[i]-1]; 62 //将h先减去首字母的1的长度,保持前缀相同前提下不断增加 63 if(h>0)h--; 64 for(;j+h<n&&i+h<n;++h){ 65 if(S[j+h]!=S[i+h])break; 66 } 67 lcp[Rank[i]-1]=h; 68 } 69 } 70 int main (){ 71 //freopen("in.txt","r",stdin); 72 //freopen("out.txt","w",stdout); 73 ios::sync_with_stdio(false); 74 int t; 75 string S; 76 cin>>t; 77 while(t--){ 78 cin>>S; 79 int m = S.length(); 80 S+=S; 81 construct_sa(S,SA); 82 construct_lcp(S,SA,LCP); 83 int N = 2*m; 84 int pos =0; 85 int ans; 86 for(int i=0;i<=N;++i){ 87 if(SA[i]<m){ 88 pos =i; 89 ans = SA[pos]+1; 90 break; 91 } 92 } 93 while(LCP[pos]>=m){ 94 pos++; 95 ans = min(SA[pos]+1,ans); 96 } 97 cout<<ans<<endl; 98 } 99 }
标签:style blog http color io os ar for sp
原文地址:http://www.cnblogs.com/shuzy/p/4035495.html