题意:给两个字符串,求一个最短的子串。使得这个子串在两个字符串中出现的次数都等于1.出现的定义为:能够重叠的出现。

解法:后缀数组的应用。从小枚举长度。假设一个长度len合法的话:则一定存在这个样的sa[i]排名。sa[i]与s[i+1]的公共前缀长度大于等于len,且sa[i]与[i-1]的公共前缀长度小于len,同一时候sa[i+1]与[i+2]的公共前缀长度小于len,同一时候保证sa[i]与sa[i+1]在两个串中。Judge函数就是技巧性地实现了这些推断。

代码:

#include<iostream>
#include<string>
#include <cstring>
#include <string.h>
#include <stdio.h>
using namespace std;
const int MAX = 200100; int n, num[MAX];
int sa[MAX], Rank[MAX], height[MAX];//sa[i]表示排名第i的后缀的位置,height[i]表示后缀SA[i]和SA[i-1]的最长公共前缀
int wa[MAX], wb[MAX], wv[MAX], wd[MAX];//名次数组 Rank[i] 保存的是 Suffix(i) 在全部后缀中从小到大排列的 “ 名次 ” 。
//简单的说,后缀数组(SA)是 “ 排第几的是谁? ” ,名次数组(RANK)是 “ 你排第几? ” 。 easy看出,后缀数组和名次数组为互逆运算。 int cmp(int *r, int a, int b, int l)
{
return r[a] == r[b] && r[a+l] == r[b+l];
} void da(int *r, int n, int m) // 倍增算法0(nlgn)。
{
int i, j, p, *x = wa, *y = wb, *t;
for(i = 0; i < m; i ++) wd[i] = 0;
for(i = 0; i < n; i ++) wd[x[i]=r[i]] ++;
for(i = 1; i < m; i ++) wd[i] += wd[i-1];
for(i = n-1; i >= 0; i --) sa[-- wd[x[i]]] = i;
for(j = 1, p = 1; p < n; j *= 2, m = p)
{
for(p = 0, i = n-j; i < n; i ++) y[p ++] = i;
for(i = 0; i < n; i ++) if(sa[i] >= j) y[p ++] = sa[i] - j;
for(i = 0; i < n; i ++) wv[i] = x[y[i]];
for(i = 0; i < m; i ++) wd[i] = 0;
for(i = 0; i < n; i ++) wd[wv[i]] ++;
for(i = 1; i < m; i ++) wd[i] += wd[i-1];
for(i = n-1; i >= 0; i --) sa[-- wd[wv[i]]] = y[i];
for(t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i ++)
{
x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p - 1: p ++;
}
}
} void calHeight(int *r, int n) // 求height数组。
{
int i, j, k = 0;
for(i = 0; i < n; i ++) Rank[sa[i]] = i;
for(i = 0; i < n; height[Rank[i ++]] = k)
{
for(k ? k -- : 0, j = sa[Rank[i]-1]; r[i+k] == r[j+k]; k ++);
}
} int len1=0;
int len2=0;
char s1[10000];
char s2[10000];
bool Judge(int n,int k)
{
int a = 0,b = 0;
for(int i = 0;i < n;i++)
{
if(height[i] < k)
{
if(a == 1 && b == 1) return 1;
a = b = 0;
}
if(sa[i] >= 0 && sa[i] < len1) a++;
if(sa[i] > len1 && sa[i] < n-1) b++;
}
return 0;
}
int main()
{
scanf("%s%s",s1,s2);
len1=strlen(s1);
len2=strlen(s2);
for(int i=0; i<len1; i++)
num[i]=s1[i]-'a'+1;
num[len1]=28;
for(int i=0; i<len2; i++)
num[i+len1+1]=s2[i]-'a'+1; da(num,len1+len2+2,30);
calHeight(num,len1+len2+2); int len=min(len1,len2);
int ans=-1;
for(int i=1; i<=len; i++)
{
if(Judge(len1+len2+2,i))
{
ans=i;
break;
}
}
cout<<ans<<endl;
return 0;
}
//20 5 19 20 19 5 20 19 5 19 28 20 5 5 16 20 5 19 0 0 0

CF(427D-Match &amp; Catch)后缀数组应用的更多相关文章

  1. CF 427D Match &amp; Catch 求最短唯一连续LCS

    题目来源:CF 427D Match & Catch 题意:给出2个字符串 求最短的连续的公共字符串 而且该字符串在原串中仅仅出现一次 思路:把2个字符串合并起来求height 后缀数组hei ...

  2. CF #244 D. Match & Catch 后缀数组

    题目链接:http://codeforces.com/problemset/problem/427/D 大意是寻找两个字符串中最短的公共子串,要求子串在两个串中都是唯一的. 造一个S#T的串,做后缀数 ...

  3. Codeforces 427D Match &amp; Catch(后缀自动机)

    [题目链接] http://codeforces.com/problemset/problem/427/D [题目大意] 给出一个两个字符串,求出最短且在两个字符串中唯一的公共子串. [题解] 以原字 ...

  4. codeforces 427D Match & Catch(后缀数组,字符串)

    题目 参考:http://blog.csdn.net/xiefubao/article/details/24934617 题意:给两个字符串,求一个最短的子串.使得这个子串在两个字符串中出现的次数都等 ...

  5. cf244D. Match &amp; Catch 字符串hash (模板)或 后缀数组。。。

    D. Match & Catch 能够用各种方法做.字符串hash.后缀数组,dp.拓展kmp,字典树.. . 字符串hash(模板) http://blog.csdn.net/gdujian ...

  6. CF 504E Misha and LCP on Tree(树链剖分+后缀数组)

    题目链接:http://codeforces.com/problemset/problem/504/E 题意:给出一棵树,每个结点上有一个字母.每个询问给出两个路径,问这两个路径的串的最长公共前缀. ...

  7. CF 504E Misha and LCP on Tree——后缀数组+树链剖分

    题目:http://codeforces.com/contest/504/problem/E 树链剖分,把重链都接起来,且把每条重链的另一种方向的也都接上,在这个 2*n 的序列上跑后缀数组. 对于询 ...

  8. CF 504 E —— Misha and LCP on Tree —— 树剖+后缀数组

    题目:http://codeforces.com/contest/504/problem/E 快速查询LCP,可以用后缀数组,但树上的字符串不是一个序列: 所以考虑转化成序列—— dfs 序! 普通的 ...

  9. Codeforces 427 D. Match &amp; Catch

    后缀数组.... 在两个串中唯一出现的最小公共子串 D. Match & Catch time limit per test 1 second memory limit per test 51 ...

随机推荐

  1. acdream 1222 Quantization Problem [dp]

    称号:acdream 1222 Quantization Problem 题意:给出一个序列 a ,然后给出一个 n * m 的矩阵,让你从这个矩阵中选出一个序列k,使得sum(abs(ki - ai ...

  2. Patch to solve sqlite3_int64 error when building Python 2.7.3 on RHEL/CentOS

    Patch to solve sqlite3_int64 error when building Python 2.7.3 on RHEL/CentOS Patch to solve sqlite3_ ...

  3. SQL_由创建表引出

    ***********************************************声明*************************************************** ...

  4. Java对象序列化/反序列化的注意事项

    Java对象序列化 对于一个存在Java虚拟机中的对象来说,其内部的状态只是保存在内存中.JVM退出之后,内存资源也就被释放,Java对象的内部状态也就丢失了.而在很多情况下,对象内部状态是需要被持久 ...

  5. 《深入理解OSGi:Equinox原理、应用与最佳实践》笔记_2_建立开发环境

    本文对应书本5.1.3的内容 书本中通过CVS下载的源码 但是笔者实践的时候发现无法下载...地址已经失效了(也许是笔者的失误输错地址所致) 可以用git下载 地址是: http://git.ecli ...

  6. CSDN 四川大学线下编程比赛第二题:Peter的X

    题目详情: http://student.csdn.net/mcs/programming_challenges Peter是个小男孩.他总是背不清26个英文字母. 于是,刁钻的英语老师给他布置了一个 ...

  7. 命令含执行JAVA程序

    1.当类没有包名时 javac Test.java java Test   2.当有包名情况下 package com.me.Test; javac -d . Test.java java com.m ...

  8. windows phone xaml文件中元素及属性(10)

    原文:windows phone xaml文件中元素及属性(10) Textblock xaml文件和隐藏文件 在设计界面的时候我们可以通过xaml中进行设计,这种设计是所见即所得的,很是方便,由于x ...

  9. python之字符串的分割和拼接

    关于string的split 和 join 方法 对导入os模块进行os.path.splie()/os.path.join() 貌似是处理机制不一样,但是功能上一样. 1.string.split( ...

  10. HDU 2504 又见GCD

    又见GCD Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...