absi2011's Blog & Daily Life.

全新的开始       我要省选翻盘       I wanna AK in 高考\化学       自此,生无可恋
[破碎的状态] BZOJ 1030 文本生成器
[破碎的状态] BZOJ 2809

[破碎的状态] BZOJ 3670

absi2011 posted @ Apr 20, 2016 09:48:40 AM in 刷题记录 with tags 字符串 KMP 小高考 bzoj , 633 阅读

心结之一..

照着别人的题解...AC了..

推荐个blog看看:http://www.cnblogs.com/rausen/p/4135811.html

显然第一次kmp大家都会的~(自己似乎还不是很会>_<)

第二次kmp..

似乎..跟第一次差不多..

只是还要求一个sum代表有几种匹配方案

那么sum[i] = sum[next[i]] + 1(next数组如题面所说)

Special: sum[-1] = -1

那么我们就能求出sum数组,而第二次的kmp数组就是拿着第一次的next向前走..

如果发现超过了i/2强行给它跳pre即可

那么这样就有了第二次kmp的num数组(和原题不一样..)

那么原题中要求的那个数组的值就是sum[num[i]]+1了,因为跳过去以后的任意一个方案及其本身都是这个字符串的一个方案

嗯差不多就这样..最后再+1变成sum[num[i]]+2....

代码:

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<time.h>
#include<bitset>
#include<vector>
#include<memory>
#include<utility>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
char a[1000005];
int next[1000005],num[1000005];
int sum[1000005];
const int modo=1000000007;
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    int t;
    scanf("%d",&t);
    int zu;
    for (zu=0;zu<t;zu++)
    {
        scanf("%s",a);
        int i;
        for (i=0;a[i]!='\0';i++)
        {
            if (i==0)
            {
                next[i]=-1;
                sum[i]=0;
                #ifdef absi2011
                printf("-1");
                #endif
                continue;
            }
            else
            {
                next[i]=next[i-1]+1;
            }
            for (;;)
            {
                if (a[i]==a[next[i]]) break;
                if (next[i]==0)
                {
                    next[i]=-1;
                    break;
                }
                next[i]=next[next[i]-1]+1;
            }
            if (next[i]!=-1)
            {
                sum[i]=sum[next[i]]+1;
            }
            else
            {
                sum[i]=0;
            }
            #ifdef absi2011
            printf(" %d",next[i]);
            #endif
        }
        #ifdef absi2011
        printf("\n");
        #endif
        int p=1;
        for (i=0;a[i]!='\0';i++)
        {
            if (i==0)
            {
                num[i]=-1;
                #ifdef absi2011
                printf("%d",num[i]);
                #endif
                continue;
            }
            else
            {
                num[i]=num[i-1]+1;
                for (;;)
                {
                    if (num[i]<=(i-1)/2) break;
                    num[i]=next[num[i]-1]+1;
                }
            }
            for (;;)
            {
                if (a[i]==a[num[i]]) break;
                if (num[i]==0)
                {
                    num[i]=-1;
                    break;
                }
                num[i]=next[num[i]-1]+1;
            }
            if (num[i]!=-1)
            {
                p=(long long)p*(sum[num[i]]+2)%modo;
            }
            #ifdef absi2011
            printf(" %d ",num[i]);
            #endif
        }
        #ifdef absi2011
        printf("\n");
        #endif
        printf("%d\n",p);
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter