【bzoj1398】Vijos1382寻找主人 Necklace 最小表示法

来源:互联网 发布:什么是java迭代器 编辑:程序博客网 时间:2024/04/29 13:56

这道题只需要把原串复制一遍,然后拿另一个串去匹配就可以了。

但是作死学了下最小表示法。

http://wenku.baidu.com/link?url=disErIxplfqlFvdZy2Zy3q7FO0hYvLBqy0rFbLe93vJfNSJM5BIh4Mh3eWq0a2NPJo-09kbvFPMgyVJ07BPyNQGiw8QPCWrtPYi-RyrULDK

最小表示法是判断两个字符串是否循环同构的东西?

其实只是一种应用。

论文里写的很详细,通过一些操作得到,如果两个字符串的最小表示相同,则这两个字符串相同。

那么就是求两个字符串的最小表示。

记两个指针i,j,任意时刻它们都不能相同,记当前匹配长度为k。

如果s[i+k]=s[j+k],那么k++

如果s[i+k]>s[j+k],那么因为[i,i+k-1]与[j,j+k-1]是相同的,所以在[i,i+k-1]中不可能有最小表示,所以i+=k+1,此时k=0。

如果s[i+k]<s[j+k],那么同上。

初始时i=0,j=1就可以了。


#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>#define maxn 1000100 using namespace std; char s[2][maxn];int n,m; int calc(char *s){    int n=strlen(s);    int i=0,j=1,k=0;    while (i<n && j<n && k<n)    {        if (s[(i+k)%n]==s[(j+k)%n]) k++;        else        {            if (s[(i+k)%n]>s[(j+k)%n]) i+=k+1;            else j+=k+1;            if (i==j) i++;            k=0;        }    }    return min(i,j);} int main(){    scanf("%s%s",s[0],s[1]);    n=strlen(s[0]);    int j=calc(s[0]),k=calc(s[1]);    bool w=0;    for (int i=0;i<n;i++)      if (s[0][(j+i)%n]!=s[1][(k+i)%n]) {w=1;break;}    if (w) printf("No\n");    else    {        printf("Yes\n");        for (int i=0;i<n;i++) printf("%c",s[0][(j+i)%n]);        printf("\n");    }    return 0;}


0 0
原创粉丝点击