poj 2406 Power Strings (kmp 中 next 数组的应用||后缀数组)
http://poj.org/problem?id=2406
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 27003 | Accepted: 11311 |
Description
Input
Output
Sample Input
abcd
aaaa
ababab
.
Sample Output
1
4
3 思路:
理解next数组,利用next数组进行巧妙求解
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
#define MAX 1000000 void get_next(char *str,int *next)
{
int i=,j=-;
int tlen=strlen(str);
next[]=-;
while(i<tlen)
{
if(j==-||str[i]==str[j])
{
i++;
j++;
if(str[i]!=str[j])
next[i]=j;
else
next[i]=next[j];
}
else
j=next[j];
}
}
char str[MAX+];
int next[MAX+];
int main()
{
int t=;
while(~scanf("%s",str))
{
if(str[]=='.') break;
get_next(str,next);
int len = strlen(str);
// for(int i=0;i<=len;i++) cout<<next[i]<<" "; cout<<endl;
if(len%(len-next[len])==) //next[len]为匹配到len时失配所要跳到的上一个匹配点,len-next[len]即为一个循环节
printf("%d\n",len/(len-next[len]));
else
printf("1\n");
}
return ;
}
(后缀数组)思路:
给定一个字符串L,已知这个字符串是由某个字符串S重复R次而得到的,求R的最大值。
算法分析:
做法比较简单,穷举字符串S的长 k,然后判断是否满足。判断的时候,先看字符串L的长度能否被k整除,再看suffix(1)和suffix(k+1)的最长公共前缀是否等于n-k。在询问最长公共前缀的时候,suffix(1)是固定的,所以RMQ问题没有必要做所有的预处理,只需求出height数组中的每一个数到height[rank[1]]之间的最小值即可。整个做法的时间复杂度为O(n)。
以下是我超时代码:(尼玛滴不科学呀!!!)
TLE代码:跪求大神赐教!!!
#include <iostream>
#include <stdio.h>
#include<string.h> using namespace std; #define maxn 1100000 #define cls(x) memset(x, 0, sizeof(x)) int wa[maxn],wb[maxn],wv[maxn],wss[maxn]; int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];} //倍增算法
void da(char *r,int *sa,int n,int m)
{
cls(wa);
cls(wb);
cls(wv);
int i,j,p,*x=wa,*y=wb,*t; //基数排序
for(i=;i<m;i++) wss[i]=;
for(i=;i<n;i++) wss[x[i]=r[i]]++;
for(i=;i<m;i++) wss[i]+=wss[i-];
for(i=n-;i>=;i--) sa[--wss[x[i]]]=i; // 在第一次排序以后,rank数组中的最大值小于p,所以让m=p。整个倍增算法基本写好,代码大约25行。
for(j=,p=;p<n;j*=,m=p)
{
//接下来进行若干次基数排序,在实现的时候,这里有一个小优化。基数排序要分两次,第一次是对第二关键字排序,第二次是对第一关键字排序。对第二关键字排序的结果实际上可以利用上一次求得的sa直接算出,没有必要再算一次
for(p=,i=n-j;i<n;i++) y[p++]=i;
for(i=;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; //其中变量j是当前字符串的长度,数组y保存的是对第二关键字排序的结果。然后要对第一关键字进行排序,
for(i=;i<n;i++) wv[i]=x[y[i]];
for(i=;i<m;i++) wss[i]=;
for(i=;i<n;i++) wss[wv[i]]++;
for(i=;i<m;i++) wss[i]+=wss[i-];
for(i=n-;i>=;i--) sa[--wss[wv[i]]]=y[i]; //这样便求出了新的sa值。在求出sa后,下一步是计算rank值。
for(t=x,x=y,y=t,p=,x[sa[]]=,i=;i<n;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
} int rank[maxn],height[maxn]; //得到height数组:排名相邻的两个后缀的最长公共前缀
void calheight(char *r,int *sa,int n)
{
cls(rank);
cls(height);
int i,j,k=; for(i=;i<n;i++) rank[sa[i]]=i;
// for(i=0;i<n;i++) printf("%d ",rank[i]); putchar(10); system("pause"); for(i=;i<n;height[rank[i++]]=k)
for(k?k--:,j=sa[((rank[i]-<)?:rank[i]-)];r[i+k]==r[j+k]&&i!=j;k++);
return;
} char ca[maxn];
int sa[maxn];
int N;
int minh[maxn]; int main()
{
int i;
while (~scanf("%s",ca))
{
N = strlen(ca);
if(ca[]=='.') break;
ca[N] = '#';
N++;
da(ca, sa, N, );
calheight(ca,sa,N); // for(i=0;i<N;i++) cout<<rank[i]<<" "; cout<<endl;
// for(i=0;i<N;i++) cout<<height[i]<<" "; cout<<endl; // for(i=0;i<N;i++) cout<<sa[i]<<" "; cout<<endl;
int i; int mins = height[rank[]];
for(i=rank[];i>;i--)
{
if(mins>height[i])
{
mins = height[i];
}
minh[i-] = mins;
}
mins = height[rank[]];
for(i=rank[];i<N;i++)
{
if(mins>height[i])
{
mins = height[i];
}
minh[i] = mins;
} for (i=;i<N;i++)
{
if ((N-) % i==&&minh[rank[i]]==N--i)
{
printf("%d\n",(N-) / i);
break;
}
}
}
return ;
}
poj 2406 Power Strings (kmp 中 next 数组的应用||后缀数组)的更多相关文章
- POJ 2406 Power Strings (KMP)
Power Strings Time Limit: 3000MSMemory Limit: 65536K Total Submissions: 29663Accepted: 12387 Descrip ...
- poj 2406 Power Strings kmp算法
点击打开链接 Power Strings Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 27368 Accepted: ...
- poj 2406 Power Strings(KMP变形)
Power Strings Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 28102 Accepted: 11755 D ...
- POJ 2406 Power Strings KMP算法之next数组的应用
题意:给一个字符串,求该串最多由多少个相同的子串相接而成. 思路:只要做过poj 1961之后,这道题就很简单了.poj 1961 详细题解传送门. 假设字符串的长度为len,如果 len % (le ...
- POJ 2406 - Power Strings - [KMP求最小循环节]
题目链接:http://poj.org/problem?id=2406 Time Limit: 3000MS Memory Limit: 65536K Description Given two st ...
- POJ 2406 Power Strings KMP运用题解
本题是计算一个字符串能完整分成多少一模一样的子字符串. 原来是使用KMP的next数组计算出来的,一直都认为是能够利用next数组的.可是自己想了非常久没能这么简洁地总结出来,也仅仅能查查他人代码才恍 ...
- POJ 2406 Power Strings KMP求周期
传送门 http://poj.org/problem?id=2406 题目就是求循环了几次. 记得如果每循环输出为1.... #include<cstdio> #include<cs ...
- poj 2406 Power Strings KMP匹配
对于数组s[0~n-1],计算next[0~n](多计算一位). 考虑next[n],如果t=n-next[n],如果n%t==0,则t就是问题的解,否则解为1. 这样考虑: 比方字符串"a ...
- poj 2406 Power Strings 后缀数组解法
连续重复子串问题 poj 2406 Power Strings http://poj.org/problem?id=2406 问一个串能否写成a^n次方这种形式. 虽然这题用kmp做比较合适,但是我们 ...
随机推荐
- 你真的会用UIButton吗? UIButton详细介绍
本节知识点: 什么是UIButton UIButton的状态 UIButton的属性设置 UIButton基本使用步骤 UIButton的代码创建与常用属性设置 重写按钮的某个状态属性的 setter ...
- NGINX server配置中if的用法
server的配置以php为例,如下: 1 server{ 2 root /var/webproject/www/mytools-php; 3 index index.html index.php; ...
- JVM垃圾回收日志结构分析
我们在我们Server的gc log上经常看到下面的这个日志: 总结一下各个字段表达的是什么意思: Young GC Full GC: top -H -P $PID 动态查看java线程的消耗情况 ...
- [原]Eclipse 安装SVN、Maven插件(补充)
参考雨之殇的文章:Eclipse 安装SVN.Maven插件 1.SVN可以按文章介绍的正常安装 2.Maven的Eclipse插件地址有变化 文章中的安装链接已经失效:m2e - http://m2 ...
- 修改Atom 隐藏.gitignore忽略的文件/文件夹的配置
参考链接:.gitignored files are hidden from tree view regardless of setting 假如Atom打开的文件夹有.gitignore 文件,会隐 ...
- CentOS 7.x安装ELK(Elasticsearch+Logstash+Kibana)
第一次听到ELK,是新浪的@ARGV 介绍内部使用ELK的情况和场景,当时触动很大,原来有那么方便的方式来收集日志和展现,有了这样的工具,你干完坏事,删除日志,就已经没啥作用了. 很多企业都表示出他们 ...
- (转)战斗bug技巧全攻略
原文地址:http://www.cnblogs.com/manuosex/p/3736077.html 程序员不是有一幅这样的对联吗 上联:一个项目两部电脑三餐盒饭只为四千工资搞得五脏俱损六神无主仍然 ...
- 3 WPF之从0开始学习XMAL
转载:http://blog.csdn.net/fwj380891124/article/details/8088233 剖析最简单的XMAL代码: <Window x:Class=&quo ...
- sql server 查询字符串指定字符出现的次数
这里提取指定符串"A"在字段中的出现次数SQL为: select len(keyword)-len(replace(keyword, 'A', ' ')) from 表 原理:用r ...
- ###Maintainable C++
点击查看Evernote原文. #@author: gr #@date: 2014-08-15 #@email: forgerui@gmail.com 记录一些标准规范.让自己的编码更可读,更可维护. ...