【KMP】ZOJ 3587
2012-03-13 00:55
441 查看
利用了kmp的性质,kmp可以找出前i个在主串出现的次数(可覆盖),同样也可以找出后j个在主串出现的次数,只需要反向kmp就行了==,具体实现是两次预处理正向&反向,然后记录num1和num2数组
所以复杂度是线性时间.....理解kmp是重点!
所以复杂度是线性时间.....理解kmp是重点!
#define N 100005 char s ,t ; int next1 ,next2 ; int num1 ,num2 ;//记录i左边在主串出现次数和i右边的 int l1,l2; void gao1(){ int i,j=-1; next1[0] = -1; for(i=1;i<l2;i++){ while(j>=0 && t[i]!=t[j+1]){ j = next1[j]; } if(t[i]==t[j+1])j++; next1[i] = j; } } void gao2(){ int i,j = l2; next2[l2-1] = l2; for(i=l2-2;i>=0;i--){ while(j<l2 && t[i]!=t[j-1]){ j = next2[j]; } if(t[i]==t[j-1])j--; next2[i] = j; } } void gaogao(){ int i,j = -1; for(i=0;i<l1;){ if(s[i]==t[j+1]){ num1[j+1]++; i++,j++; } else { if(j!=-1){ j = next1[j]; } else i++; } } for(i=l2-1;i>=0;i--){ if(num1[i]){ if(next1[i]!=-1){ num1[next1[i]]+=num1[i]; } } } /////////////////////////////////////////////////////// j = l2; for(i=l1-1;i>=0;){ if(s[i]==t[j-1]){ num2[j-1]++; i--,j--; } else { if(j!=l2){ j = next2[j]; } else i--; } } for(i=0;i<l2;i++){ if(num2[i]){ if(next2[i]!=l2){ num2[next2[i]] += num2[i]; } } } } int main(){ int ca; scanf("%d",&ca); while(ca--){ scanf("%s%s",s,t); int i,j; l1 = strlen(s); l2 = strlen(t); memset(num1,0,sizeof(num1)); memset(num2,0,sizeof(num2)); gao1(); gao2(); gaogao(); LL ans = 0; for(i=0;i+1<l2;i++){ ans += (LL)num1[i]*(LL)num2[i+1]; } printf("%lld\n",ans); } return 0; }
相关文章推荐
- zoj 3587 蛮好的KMP题
- ZOJ 题目3587 Marlon's String(KMP)
- ZOJ 3587 扩展KMP
- ZOJ 3587 Marlon's String 扩展KMP
- 【KMP】ZOJ-3587-Marlon's String
- ZOJ 3587 Marlon's String 扩展KMP
- [zoj 3587]Marlon's String[kmp]
- Zoj 3587 Marlon's String (KMP 字符串拼接 前缀出现次数)
- ZOJ 3587 扩展KMP应用
- ZOJ 3587 扩展KMP
- ZOJ 题目3587 Marlon's String(KMP)
- zoj 1905 ||poj 2406 Power Strings(KMP||暴力)
- zoj——3957多重KMP
- zoj 2177 Period (KMP )
- zoj 2619 KMP+高斯消元+概率求期望
- 【ZOJ】3785 What day is that day? ——KMP 暴力打表找规律
- zoj 2587 kmp的应用
- zoj 3785 What day is that day?(找规律,KMP)
- zoj 3587 Marlon's String
- KMP和扩展KMP ZOJ 3817 Chinese Knot