poj 2406 Power Strings(KMPnext性质)

【题目大意】:给出一个字符串,将其分解为若干子串的和,求可分解的最多子串的个数。

Sample Input

abcd aaaa ababab .

Sample Output

1 4 3

【解题思路】:
利用next数组的性质:
如果len%(len-next[len-1])==0,则字符串中必存在最小循环节,且循环次数即为 len/(len-next[len-1]) 其中len为所给字符串的长度!  
证明:
必要性:因为字符串中存在最小循环节(设长度为k)next[len-1]=len-k,所以len%(len-next[len-1])==0;
  充分性:令k1=len-next[len-1],由于k1整除len,所以可以相应的把len划分为n片区域(n=len/(k1))从小到大依次表示为
t1,t2...tn;next数组的定义可知,t1=t2,t2=t3,...t(n-1)=tn,且相应的片区域即为最小,所以循环次数也为len/(len-next[len-1]);

【代码】:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
                   
using namespace std;
                   
#define eps 1e-8
#define pi acos(-1.0)
#define inf 1<<30
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long

char s[1000010];
int next[1000010],sn,temp;

void solve_kmp_next(){
    next[0]=0;
    sn=strlen(s);
    for(int i = 1; i < sn; i++){
        temp=next[i-1];
    while(temp && s[temp]!=s[i])
        temp=next[temp-1];
    if(s[temp]==s[i])
        next[i]=temp+1;
    else
        next[i]=0;
    }   
    return ;
}
int main(){
    while (~scanf("%s",s)){
        if (s[0]=='.') return 0;
        solve_kmp_next();
        if(sn%(sn-next[sn-1])==0)
            printf("%d\n",sn/(sn-next[sn-1]));
        else
            printf("1\n");     
  }
  return 0;   
}
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值