CodeForces 25E Test KMP

题目链接:点击打开链接

题意:

给定3个字符串,进行拼接

重复的一段可以覆盖,问拼接后最小的长度(若一个串s1是s2的子串,则s1可以认为嵌入了s2内,不需要进行拼接

思路:

kmp搞一下。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <set>
using namespace std;
#define N 300005
char T[N];//从0开始存
int f[N];//记录P的自我匹配
void getFail(int len, char *P)
{
    int i = 0, j = -1;
    f[0] = -1;
    while(i != len)
    {
        if(j == -1 || P[i] == P[j])
            f[++i] = ++j;
        else
            j = f[j];
    }
}
int KMP(int *f2, char *S1, char *S2, int lens1, int lens2){   //f2是S2的失配数组
	getFail(lens2, S2);
    int pos = 0, len = lens1, j = 0, i = 0;
	int gg = 0;
    while(i <= len)
    {
        while(j!=-1 && S1[i] != S2[j]) j = f2[j];
        i++, j++;
		gg = max(j, gg);
        if(i == len) {
			pos = max(pos, j);
		}
    }
	if(gg == lens2)return gg;
    return pos;  //这样得到的是S1的尾部和S2的前缀的  最大匹配位置(在S2中的位置)
}/* */
char s[3][N/3];
char tmp[N];
int l[3];
int hehe(int a,int b,int c){
	int pos = KMP(f, s[a], s[b], l[a], l[b]);

	for(int i = 0; i < l[a]; i++)tmp[i] = s[a][i];
	int top = l[a];
	if(pos!=l[b])
	for(; pos<l[b]; pos++)tmp[top++] = s[b][pos];
	tmp[top] = 0;
	pos = KMP(f, tmp, s[c], top, l[c]);
	return top+(l[c]-pos);
}
int main(){
	int i, j, u, v;
	while(~scanf("%s",s[0])){
		scanf("%s",s[1]);
		scanf("%s",s[2]);
		for(i=0;i<3;i++)l[i]=strlen(s[i]);
		int ans = hehe(0,1,2);
		ans = min(ans, hehe(0,2,1));
		ans = min(ans, hehe(1,0,2));
		ans = min(ans, hehe(1,2,0));
		ans = min(ans, hehe(2,0,1));
		ans = min(ans, hehe(2,1,0));
		cout<<ans<<endl;
	}
	return 0;
}
/*
xufuzdlsjxmevrtessfbwlnzzclcqwevnnucxyvhngnxhcbdfwq
wlwobhnmmgtfolfaeckbrnnglylydxtgtvrlmeeszoiuatzzzxufuzdlsjxmevrt
brnnglylydxtgtvrlmeeszoiuatzzzx

syvncqmfhautvxudqdhggz
hrpxzeghsocjpicuixskfuzupytsgjsdiyb
ybcmnmnbpndbxlxbzhbfnqvwcffvrdhtickyqhupmcehls
aa
aa
aa
a
b
c
xab
abx
c
x
ab
ab

*/

CodeForces 25E Test KMP,布布扣,bubuko.com

时间: 2024-10-12 19:53:53

CodeForces 25E Test KMP的相关文章

Codeforces 471D 差分+kmp

题意 给出两个长度为n,m的a,b序列 问n中有多少个连续长度为m的序列,同时加/减去某一个数后和b相同 c序列同时加上/减去某个数,其相邻差不变. 算出相邻差,跑一遍kmp即可 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=3e6+20; int n,m,a[N],b[N],c[N],d[N]; int fail[N]; void getfail() { int i=0,j=-1

Codeforces 126B. Password (KMP)

<题目链接> 题目大意:给定一个字符串,从中找出一个前.中.后缀最长公共子串("中"代表着既不是前缀,也不是后缀的部分). 解题分析:本题依然是利用了KMP中next数组的性质.具体做法见代码. #include <bits/stdc++.h> using namespace std; const int N = 1e6+5; char str[N]; int vis[N],nxt[N]; void getNext(int len){ int j=0,k=-1;

Codeforces 126B(kmp)

要点 头尾的最长相同只要一个kmp即可得,于是处理中间部分 扫一遍记录一下前缀的每个位置是否存在一个中间串跟它相同,见代码 如果当前没有,接着用Next数组去一找即可 #include <cstdio> #include <cstring> const int maxn = 1e6 + 5; char s[maxn]; int Next[maxn], Has[maxn], flag; int main() { scanf("%s", s + 1); int n

Codeforces 1137B(kmp next数组构造)

为了物尽其用,Next求出最多有哪部分能重复使用,然后重复使用就行了-- const int maxn = 5e5 + 5; char s[maxn], t[maxn]; int cnts0, cnts1, cntt0, cntt1; int Next[maxn]; int main() { ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin >> (s + 1) >> (t + 1); int lens = str

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

题目链接:Educational Codeforces Round 21 G. Anthem of Berland 题意: 给你两个字符串,第一个字符串包含问号,问号可以变成任意字符串. 问你第一个字符串最多包含多少个第二个字符串. 题解: 考虑dp[i][j],表示当前考虑到第一个串的第i位,已经匹配到第二个字符串的第j位. 这样的话复杂度为26*n*m*O(fail). fail可以用kmp进行预处理,将26个字母全部处理出来,这样复杂度就变成了26*n*m. 状态转移看代码(就是一个kmp

codeforces 825F F. String Compression dp+kmp找字符串的最小循环节

/** 题目:F. String Compression 链接:http://codeforces.com/problemset/problem/825/F 题意:压缩字符串后求最小长度. 思路: dp[i]表示前i个字符需要的最小次数. dp[i] = min(dp[j]+w(j+1,i)); (0<=j<i); [j+1,i]如果存在循环节(自身不算),那么取最小的循环节x.w = digit((i-j)/x)+x; 否则w = i-j+1; 求一个区间最小循环节: 证明:http://w

Codeforces 432D Prefixes and Suffixes(KMP+dp)

题目连接:Codeforces 432D Prefixes and Suffixes 题目大意:给出一个字符串,求全部既是前缀串又是后缀串的字符串出现了几次. 解题思路:依据性质能够依据KMP算法求出全部的前后缀串,然后利用dp求解,dp[i]表示从1到i这个子串出现过的次数.转移方程dp[jump[i]]+=dp[i].随意一个dp[i]的初始状态应该是1. #include <cstdio> #include <cstring> const int N = 1e5+5; int

// codeforces 471D // kmp初学

// codeforces 471D // #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> using namespace std; int n,w; int a[200005],b[200005]; int da[200005],db[200005]; int nex

Educational Codeforces Round 25 F. String Compression(kmp+dp)

题目链接:Educational Codeforces Round 25 F. String Compression 题意: 给你一个字符串,让你压缩,问压缩后最小的长度是多少. 压缩的形式为x(...)x(...)  x表示(...)这个出现的次数. 题解: 考虑dp[i]表示前i个字符压缩后的最小长度. 转移方程解释看代码,这里要用到kmp来找最小的循环节. 当然还有一种找循环节的方式就是预处理lcp,然后通过枚举循环节的方式. 这里我用的kmp找的循环节.复杂度严格n2. 1 #inclu