SDNU 1260.Problem H. The chord 最长公共子串

1260.Problem H. The chord
Time Limit: 1000 MS    Memory Limit: 32768 KB

Description
Now lmh has already written a new GTP, he know how to play the broken chord by right hand. But as for the left hand chords, he can’t play all chords.So after he gets a new chord by random number programme, he finds a problem-- he can’t sing this song because his ability is not enough. But GTP is written, he doesn’t want to give up. Can you tell him how long can he sing continuously?

lmh is foolish. Even if he grasps a rhythm, such as ABCD, he only can play ABCD fluently, BCBC or ABCDABCD he can’t play it fluently.But as for BC, he can play it and just ignore A and D.

The guitar have a lot of the left chords. lmh just knows part of it, including C, Dm, Em, Am, F, G, D7, E, D, A, A7, Bm, B7, C7, G7, Dm7, Fmaj7, Asus4. This problem just need to deal with these chords.


Input
Input contains multiple test cases. Each test case contains two strings, each string will have at most 100000 characters.First string means the rhythm which lmh has grasped. Second string means a new rhythm by lmh’s random programme.


Output
A number means the biggest length which lmh can play.
(If he can’t play, output 0).


Sample Input
CAmFG
CAmFGCAmFG
AGAsus4D
GAsus4
B7G7
B7G7B7G7B7G7
AmFmaj7C7Dm7C7

C7Dm7C7Dm7C7


Sample Output
4
2
2

3


    除了图论Java大数,字符串在这两场比赛中也没出现过(上次的E题不算,都手算出来的......)所以当然要愉快的补一道字符串的题了~

    题意也不难懂,就是说给出两行字符串,第一行是lmh会弹的和弦,第二行是歌曲的和弦,问lmh弹这首歌最长能弹多长。但是如果lmh会ABCD,对于ABCDABCD他只能弹ABCD,对于BCBC他只能弹BC,就是说范围只能在第一行字符串中,换句话说就是求这两个字符串的最长公共子串。不过为了让这个题更恶心,我让这两个字符串的组成部分只包括C, Dm, Em, Am, F, G, D7, E, D, A, A7, Bm, B7, C7, G7, Dm7, Fmaj7, Asus4这些和弦。

    直接在网上套用了一个后缀数组的板子,然后把这些和弦都转化一下变成比如JKL这样没用过的单字符就方便比较了(表示我自己敲了一长串的for循环,一看阳敲的代码直接一个map解决了......好吧喜闻乐见的我200行代码别人50行)

    下面AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int sint[200005];
int t1[200005],t2[200005],x[200005];
int c[200005],sa[200005],ran[200005],height[200005];
char s1[200005],s[200005];
int len1;

void build_sa(int *sint,int n,int m)
{
    int i,*x=t1,*y=t2,k;
    for(i=0;i<m;i++) c[i]=0;
    for(i=0;i<n;i++) c[x[i]=sint[i]]++;
    for(i=1;i<m;i++) c[i]+=c[i-1];
    for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
    for(k=1;k<=n;k<<=1)
    {
        int p=0;
        for(i=n-k;i<n;i++) y[p++]=i;
        for(i=0;i<n;i++)  if(sa[i]>=k) y[p++]=sa[i]-k;
        for(i=0;i<m;i++) c[i]=0;
        for(i=0;i<n;i++) c[x[y[i]]]++;
        for(i=1;i<m;i++) c[i]+=c[i-1];
        for(i=n-1;i>=0;i--)  sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        p=1;
        x[sa[0]]=0;
        for(i=1;i<n;i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
        if(p>=n)
            break;
        m=p;
    }
}

void getheight(int n)
{
    int i,j,k=0;
    for(i=0;i<n;i++)
        ran[sa[i]]=i;
    for(i=0;i<n;i++)
    {
        if(k) k--;
        int j=sa[ran[i]-1];
        while(sint[i+k]==sint[j+k]) k++;
        height[ran[i]]=k;
    }
}

int change(int l)
{
    int i,j=0;
    for(i=0;i<l;i++)
    {
        if(s1[i]=='A')
        {
            if(s1[i+1]=='m')
            {
                s[j++]='H';
                i++;
            }
            else if(s1[i+1]=='7')
            {
                s[j++]='I';
                i++;
            }
            else if(s1[i+1]=='s')
            {
                s[j++]='J';
                i+=4;
            }
            else
            {
                s[j++]='A';
            }
        }
        else if(s1[i]=='B')
        {
            if(s1[i+1]=='m')
            {
                s[j++]='K';
                i++;
            }
            else
            {
                s[j++]='L';
                i++;
            }
        }
        else if(s1[i]=='C')
        {
            if(s1[i+1]=='7')
            {
                s[j++]='M';
                i++;
            }
            else
            {
                s[j++]='C';
            }
        }
        else if(s1[i]=='D')
        {
            if(s1[i+1]=='m')
            {
                if(s1[i+2]=='7')
                {
                    s[j++]='O';
                    i+=2;
                }
                else
                {
                    s[j++]='N';
                    i++;
                }
            }
            else if(s1[i+1]=='7')
            {
                s[j++]='P';
                i++;
            }
            else
            {
                s[j++]='D';
            }
        }
        else if(s1[i]=='E')
        {
            if(s1[i+1]=='m')
            {
                s[j++]='Q';
                i++;
            }
            else
            {
                s[j++]='E';
            }
        }
        else if(s1[i]=='F')
        {
            if(s1[i+1]=='m')
            {
                s[j++]='R';
                i+=4;
            }
            else
            {
                s[j++]='F';
            }
        }
        else if(s1[i]=='G')
        {
            if(s1[i+1]=='7')
            {
                s[j++]='S';
                i++;
            }
            else
            {
                s[j++]='G';
            }
        }
        else
        {
            len1=j;
            s[j++]='$';
        }
    }
    return j;
}

int main()
{
    int len,i,ans;
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    while(scanf("%s",s1)!=EOF)
    {
        memset(s,0,sizeof(s));
        memset(sint,0,sizeof(sint));
        memset(t1,0,sizeof(t1));
        memset(t2,0,sizeof(t2));
        memset(x,0,sizeof(x));
        memset(c,0,sizeof(c));
        memset(sa,0,sizeof(sa));
        memset(ran,0,sizeof(ran));
        memset(height,0,sizeof(height));
        len=strlen(s1);
        s1[len]='$';
        scanf("%s",s1+len+1);
        len=strlen(s1);
        len=change(len);
        //cout<<s<<" "<<len1<<" "<<len<<endl;
        for(i=0;i<len;i++)
            sint[i]=s[i];
        build_sa(sint,len,130);
        getheight(len);
        ans=0;
        for(i=0;i<len;i++)
        {
            if(height[i]>ans&&((sa[i-1]<len1&&sa[i]>=len1)||(sa[i-1]>=len1&&sa[i]<len1)))
                ans=height[i];
        }
        cout<<ans<<endl;
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值