Hdu 5782 Cycle(给你两个长度相同的字符串,对于长度为i的前缀,如果这两个字符串的前缀是循环相等的,那么输出1,否则输出0)
2016-08-05 18:57
411 查看
传送门:Hdu 5782 Cycle
给你两个长度相同的字符串,对于长度为i的前缀,如果这两个字符串的前缀是循环相等的,那么输出1,否则输出0
思路:两个子串循环相同->第一个子串可以被分为a1,b1,第二个子串可以被分为a2,b2,且a1=b2,b1=a2
先用一个biset处理出对于每一个字符,它在B这个字符串中出现的位置可能是哪些
然后bitset处理出a中的0-i可以和b中的那些匹配(即开头位置为哪个,用bitset记录)
这样a1=b2便已经匹配好了
接下来枚举a的起始位置,判断b的前缀和a起始位置的最大匹配长度,设为x
那么b中如果有小于等于x的i可以与a中的前缀匹配,那么这些都是合法的
给你两个长度相同的字符串,对于长度为i的前缀,如果这两个字符串的前缀是循环相等的,那么输出1,否则输出0
思路:两个子串循环相同->第一个子串可以被分为a1,b1,第二个子串可以被分为a2,b2,且a1=b2,b1=a2
先用一个biset处理出对于每一个字符,它在B这个字符串中出现的位置可能是哪些
然后bitset处理出a中的0-i可以和b中的那些匹配(即开头位置为哪个,用bitset记录)
这样a1=b2便已经匹配好了
接下来枚举a的起始位置,判断b的前缀和a起始位置的最大匹配长度,设为x
那么b中如果有小于等于x的i可以与a中的前缀匹配,那么这些都是合法的
#include<bitset> #include<cstdio> #include<cmath> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int maxn=20010; bitset<10010>st[10011],ans,Count[27],Pow[10011]; char s1[10011],s2[10011]; int s[maxn]; int sa[maxn],t1[maxn],t2[maxn],c[maxn]; //构造字符串S的后缀数组,每个字符值必须为0~m-1 void build_sa(int s[],int n,int m){ int *x=t1,*y=t2; for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<n;i++) c[x[i]=s[i]]++; for(int i=1;i<m;i++) c[i]+=c[i-1]; for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i; for(int k=1;k<=n;k<<=1){ int p=0; for(int i=n-k;i<n;i++) y[p++]=i; for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<n;i++) c[x[y[i]]]++; for(int i=0;i<m;i++) c[i]+=c[i-1]; for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(int i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k] ? p-1:p++; if(p>=n) break; m=p; } } int Rank[maxn],height[maxn],N; //getHeight(,n); void getHeight(int s[],int n){ int k=0; for(int i=0;i<=n;i++) Rank[sa[i]]=i; for(int i=0;i<n;i++){ if(k) k--; int j=sa[Rank[i]-1]; while(s[i+k]==s[j+k]) k++; height[Rank[i]]=k; } } int dp[maxn][20]; void RMQ_init(int n){ for(int i=1;i<=n;i++) dp[i][0]=height[i]; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++) dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } int rmq(int L,int R){ L=Rank[L],R=Rank[R]; if(L>R) swap(L,R); L++; int k=(int)log2(R-L+1); return min(dp[L][k],dp[R-(1<<k)+1][k]); } int main(){ Pow[0][0]=1; for(int i=1;i<=10000;i++) Pow[i]=Pow[i-1],Pow[i][i]=1; int case1=1; while(scanf("%s%s",s1,s2)!=EOF){ int len=strlen(s1),n=2*len+1; ans.reset(); for(int i=0;i<26;i++) Count[i].reset(); for(int i=0;i<len;i++) //s2中'a','b','c'...这些字符可能出现的位置 Count[s2[i]-'a'][i]=1,st[i].reset();//是否初始化 st[0]=Count[s1[0]-'a']; for(int i=1;i<len;i++) st[i]=st[i-1]&(Count[s1[i]-'a']>>i); for(int i=0;i<len;i++) s[i]=s2[i]; s[len]='*'; for(int i=0;i<=len;i++) s[i+len+1]=s1[i]; build_sa(s,n+1,128); getHeight(s,n); RMQ_init(n); for(int i=0;i<=len;i++){ if(i==0) ans[0]=(s1[0]==s2[0]); else{ int num; if(i==n+1) num=0; else num=rmq(0,i+len+1);//i+len+1表示本身这个点 ans|=((Pow[num]&st[i-1])<<(i-1)); } } for(int i=0;i<len;i++) putchar(ans[i]+'0'); putchar('\n'); } return 0; }
相关文章推荐
- 从键盘输入两个字符串,如果相等,输出match,否则输出no match。
- 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 《剑指Offer》输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 比较两个字符串是否相等,相等输出MATCH,否则NOMATCH
- hdu 1671 Phone List(给定n个电话号码串,问这n个电话号码串中是否存在某一串是其它串的前缀,如果存在输出NO,否则YES)
- 输入一个字符串,如果第一个字符是大写并且其他字符不是大写,那么输出true,否则输出false。
- 【剑指offer24】输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 求字符串中由连续的相同字符组成的最长子串(如果有两个及两个以上的最长子串,则输出第二个)
- Stirng类的常见用法:输出str长度,输出第一个"o",和最后一个"o"的索引,将str中的字符"l"替换成"m",字符串str按空格“ ”分割为2个字符串,比较这两个字符串是否相等。
- java 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
- 将输入的字符串(字符串仅包含小写字母‘a’到‘z’),按照如下规则,循环转换后输出:a->b,b->c,…,y->z,z->a;若输入的字符串连续出现两个字母相同时,后一个字母需要连续转换2次。例如:
- 比较两个字符串是否相等,相等输出MATCH,否则NOMATCH
- 、给一组字符串,需要你输出最小长度的字符串与最大长度的字符串,如果有相同最小(大)长度的,就按照给的顺序挨个输出。
- 写了一个字符串截取一定长度的代码,中文两个字符,英文一个字符,如果截断了自动用一个.或两个.来对齐,用于标题的显示
- 输入一行子串,找出其中出现的相同且长度最长的字符串,输出它及其首字符的位置
- 读入一个字符串(长度不大于100,不包括换行符’\n’),删去字符串中相同的排在后面的字符并输出。
- 求字符串中两个长度最长且相等的子串