ZOJ 3587 扩展KMP应用

点击打开链接

题意:给定两个串,问从第一个串取出连续的两段,合并后可以拼成第二个的方法总数,这两段可以有重叠的部分

思路:用扩展KMP求出extand数组,不懂KMP的可以看这篇点击打开链接,解释的很详细,extand[i](0<=i=1,第一个字符的可能性就+1;第二个也一样,只要extand[i]>=2就+1;后面的情况我们可以将字符串反过来扩展KMP一次,求得结果与前面的意义相同,看代码吧,对了,可能性不能一个一个的加,肯定超时,我用了线段树,后来才发现从后面往前加简单的一塌糊涂,too young

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int maxn=100005;
int next[maxn],extand[maxn];
char S[maxn],T[maxn];
int ans1[maxn],ans2[maxn];
int num[maxn*4],num1[maxn*4];
void GetNext(const char *T){//扩展KMP模版
     int len=strlen(T),a=0;
     next[0]=len;
     while(a= p){
             int j = (p-k+1)>0 ? (p-k+1) : 0;
             while(k+j= p){
             int j= (p-k+1) > 0 ? (p-k+1) : 0;
             while(k+j>1;
    if(l<=t) update(l,r,le,t,node<<1);
    if(r>t) update(l,r,t+1,ri,node<<1|1);
    num[node]=num[node<<1]+num[node<<1|1];
}
int query(int pos,int le,int ri,int node){
    if(le==ri) return num[node];
    pushdown(node);
    int t=(le+ri)>>1;
    int ans;
    if(pos<=t) ans=query(pos,le,t,node<<1);
    else ans=query(pos,t+1,ri,node<<1|1);
    return ans;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        memset(num,0,sizeof(num));
        memset(num1,0,sizeof(num1));
        scanf("%s%s",S,T);
        int len1=strlen(S);
        int len2=strlen(T);
        memset(ans1,0,sizeof(ans1));
        memset(ans2,0,sizeof(ans1));
        GetExtand(S,T);
        for(int i=0;i=1)
            update(1,extand[i],1,len1,1);
        }
        for(int i=1;i=1)
            update(1,extand[i],1,len1,1);
        }
        for(int i=1;i

你可能感兴趣的:(KMP,数据结构,线段树)