poj 2774
2016-05-19 19:08
363 查看
题目概述:
有两个字符串s,s2输入:
第一行s,第二行s2输入只有一组
限制:
s,s2仅含小写字母;s,s2长度<=100000;输出:
一个整数,最长公共子串的长度样例输入:
yeshowmuchiloveyoumydearmotherreallyicannotbelieveityeaphowmuchiloveyoumydearmother
样例输出:
27讨论:
题目很长,但其中包含两个关键因素,仅含小写字母和要求最长公共子串,输入中包含第三个因素,长度不过十万,输出包含最后一个因素,求其长度,看完题目这就是个模版题了,因此额也用的模版(然而根本不理解)算法正确性(fun函数最后几行)没有写,额明白,但是担心写不清楚
题解状态:
3776K,360MS,C++,1693B题解代码:
#include<string.h> #include<stdio.h> #include<iostream> #include<set> #include<map> #include<string> #include<vector> using namespace std; #define INF 0x3f3f3f3f #define maxx(a,b) ((a)>(b)?(a):(b)) #define minn(a,b) ((a)<(b)?(a):(b)) #define MAXN 200006//多数操作建立在两个字符串合并后的基础上,因此是双倍 #define memset0(a) memset(a,0,sizeof(a)) char s[MAXN];//string,最后会合并另一个字符串到这里,因此是双倍 int n, sa[MAXN], height[MAXN], rk[MAXN], tmp[MAXN], top[MAXN];//suffix array,height,rank,temporary,top这一行是模版的数据结构,rank由于和stl有二义性而改名 int s1len, slen;//string 1 length, string length,这里的s1是合并之前的s的长度,s是合并之后的长度 void makesa()//这是模版,倍增算法构造sa数组和rk数组 { int i, j, len, na; na = (n < 256 ? 256 : n); memset(top, 0, na*sizeof(int)); for (i = 0; i < n; i++) top[rk[i] = s[i] & 0xff]++; for (i = 1; i < na; i++) top[i] += top[i - 1]; for (i = 0; i < n; i++) sa[--top[rk[i]]] = i; for (len = 1; len < n; len <<= 1) { for (i = 0; i < n; i++) { j = sa[i] - len; if (j < 0) j += n; tmp[top[rk[j]]++] = j; } sa[tmp[top[0] = 0]] = j = 0; for (i = 1; i < n; i++) { if (rk[tmp[i]] != rk[tmp[i - 1]] || rk[tmp[i] + len] != rk[tmp[i - 1] + len]) top[++j] = i; sa[tmp[i]] = j; } memcpy(rk, sa, n*sizeof(int)); memcpy(sa, tmp, n*sizeof(int)); if (j >= n - 1) break; } } void lcp()//也是模版,求height数组 { int i, j, k; for (j = rk[height[i = k = 0] = 0]; i < n - 1; i++, k++) while (k >= 0 && s[i] != s[sa[j - 1] + k]) height[j] = (k--), j = rk[sa[j] + 1]; } int fun() { char s2[MAXN / 2];//string 2,没什么用的s2字符串 scanf("%s%s", s, s2);//input s1len = strlen(s); strcat(s, s2);//合并字符串 slen = strlen(s); n = strlen(s) + 1;//模版要求的初始化条件 makesa(); lcp(); int big = -INF;//初始化big为一个很小的数 for (int p = 1; p < slen; p++) {//遍历sa数组,由于从s每个位置开始到字符串尾的子串都在sa中,共slen个,以此做限制条件,从1开始因为下面用到p-1 if (sa[p - 1] < s1len&&sa[p] >= s1len || sa[p - 1] >= s1len&&sa[p] < s1len)//如果相邻的后缀分别属于两个字符串 big = maxx(big, height[p]);//更新最大子串长度 } return big; } int main(void) { //freopen("vs_cin.txt", "r", stdin); //freopen("vs_cout.txt", "w", stdout); printf("%d\n", fun());//output//程序会测试4次,但每次只有一组字符串 }
EOF
相关文章推荐
- 用 Dojo 1.x 开发小部件
- Android通过Wifi来调试应用
- 11、串口编程
- CSS3D效果
- VxWorks_AuxClk
- Java Decompiler
- ionic入门教程第十六课-在微信中使用ionic的解决方案(按需加载加强版)
- 怎样解决asp.net.mvc上传附件超过长度问题?
- 使用弹性盒子模型的一些思考
- SQL Server之视图及自定义 函数
- mybatis和ibatis的区别
- mybatis入门基础(六)----高级映射(一对一,一对多,多对多)
- TableView自定义左划多个按钮
- Permutations II
- Struts2自定义拦截器(待续)
- 键盘样式(UIKeyboardType)
- python部落之python刷题宝之基础知识
- Linux 线程通信
- 微博之路就此开始
- U盘安装系统