CodeForces - 427D (2020.3.22训练I题)

Problem
Police headquarter is monitoring signal on different frequency levels. They have got two suspiciously encoded strings s1 and s2 from two different frequencies as signals. They are suspecting that these two strings are from two different criminals and they are planning to do some evil task.

Now they are trying to find a common substring of minimum length between these two strings. The substring must occur only once in the first string, and also it must occur only once in the second string.

Given two strings s1 and s2 consist of lowercase Latin letters, find the smallest (by length) common substring p of both s1 and s2, where p is a unique substring in s1 and also in s2. See notes for formal definition of substring and uniqueness.

Input
The first line of input contains s1 and the second line contains s2 (1 ≤ |s1|, |s2| ≤ 5000). Both strings consist of lowercase Latin letters.

Output
Print the length of the smallest common unique substring of s1 and s2. If there are no common unique substrings of s1 and s2 print -1.

题意:给定两个字符串,求两个字符串中最短的公共子串,要求分别只出现一次

拿出后缀数组的板子,这题我们需要用到后缀数组head[i],首先将两个字符串拼接在一起,连接处可随意,我是赋值空格,拼接后的总串长度为n,我们再定义一个belong数组,belong[i]=1代表下标i的后缀字符串是一串的,2代表是二串的,0代表那个空格,所以欲使题意满足,则需要head(i)局部最大,最小长度为max(head[i-1],head[i+1])+1,遍历一遍总串得出最终答案

ac代码

/*数组sa表示排名i的子串下标是多少
,数组rak表示下标i的子串排名多少
,数组height表示LCP(i,i-1)最长公共前缀*/
#include<iostream>
using namespace std;
typedef long long ll;
const int N = 20000;
const int INF = 999999;
int wa[N], wb[N], wv[N], wss[N], rak[N], height[N], cal[N], n, sa[N];
char s[N];
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 *sa, int n, int M) 
{
     int i, j, p, *x = wa, *y = wb, *t;
     for (i = 0; i < M; i++) 
		 wss[i] = 0;
     for (i = 0; i < n; i++) 
		 wss[x[i] = r[i]]++;
     for (i = 1; i < M; i++) 
		 wss[i] += wss[i - 1];
     for (i = n - 1; i >= 0; i--) 
		 sa[--wss[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++) 
			wss[i] = 0;
        for (i = 0; i < n; i++) 
			wss[wv[i]]++;
        for (i = 1; i < M; i++) 
			wss[i] += wss[i - 1];
        for (i = n - 1; i >= 0; i--) 
			sa[--wss[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++;
     }
     return;
}
void calheight(int *r, int *sa, int n) 
{
     int i, j, k = 0;
     for (i = 1; i <= n; i++) 
		 rak[sa[i]] = i;
     for (i = 0; i < n; height[rak[i++]] = k)
     for(k ? k--: 0, j = sa[rak[i] - 1]; r[i + k] == r[j + k]; k++);
     for(int i = n; i; i--)rak[i] = rak[i - 1], sa[i]++;
}
int belong[N];

int main()
{
    int cas = 1;
	char s1[N], s2[N];
	scanf("%s%s", s1 + 1, s2 + 1);
	int len1 = strlen(s1 + 1), len2 = strlen(s2 + 1);
	for (int i = 1; i <= len1; i++)
	{
		s[i] = s1[i];
		belong[i] = 1;
	}
	s[len1 + 1] = ' ';
	for (int i = len1 + 2; i <= len1 + len2 + 1; i++)
	{
		s[i] = s2[i - len1 - 1];
		belong[i] = 2;
	}
    n = len1 + len2 + 1;

    for (int i = 1; i <= n; i++)
        cal[i] = s[i];
    cal[n + 1] = 0;//不能少
    da(cal + 1, sa, n + 1, 200);
    calheight(cal + 1, sa, n);
	int minn = INF;
    for (int i = 1; i <= n; i++)
    {
        if (belong[sa[i - 1]] + belong[sa[i]] == 3)
        {
            if (height[i - 1] < height[i] && height[i + 1] < height[i])
            {
                minn = min(minn, max(height[i - 1], height[i + 1]) + 1);
            }
        }
    }
    if(minn == INF)
		cout<<"-1"<<endl;
	else
		cout<<minn<<endl;
    
}
发布了16 篇原创文章 · 获赞 21 · 访问量 1322

猜你喜欢

转载自blog.csdn.net/rainbowower/article/details/105075540