SCAU组队专题训练-字符串

A
【题解】kmp

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define mst(a,b) memset(a,b,sizeof a)
#define MAXN 1000050
using namespace std;
int n,nexts[MAXN]; string st,s;
void get_next(string t)
{
    int i=0,j=-1,len=t.size(); nexts[0]=-1;
    while (i<len)
    {
        if (j==-1 || t[i]==t[j])
        {
            i++; j++;
            nexts[i]=j;
        }
         else j=nexts[j];
    }
    return;
}
int KMP(string &s,string &t,int pos)
{
    get_next(t);
    int i=pos,j=0,sl=s.size(),tl=t.size();
    while (i<sl && j<tl)
    {
        if (j==-1 || s[i]==t[j])
        {
            j++;i++;
        }
        else
            j=nexts[j];
    }
    return j;
}
void add(string s)
{
    int pos=KMP(st,s,max(0,(int)st.size()-(int)s.size()));
    int sl=s.size();
    for (int i=pos;i<sl;i++)
    {
        st.push_back(s[i]);
    }
}
int main()
{
	//IOS
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
    {
        cin>>s;
        if (i==1) st=s;
         else add(s);
    }
    cout<<st<<endl;
	return 0;
}

B——Seek the Name, Seek the Fame

The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the little cat to give names to their newly-born babies. They seek the name, and at the same time seek the fame. In order to escape from such boring job, the innovative little cat works out an easy but fantastic algorithm:

Step1. Connect the father’s name and the mother’s name, to a new string S.
Step2. Find a proper prefix-suffix string of S (which is not only the prefix, but also the suffix of S).

Example: Father=‘ala’, Mother=‘la’, we have S = ‘ala’+‘la’ = ‘alala’. Potential prefix-suffix strings of S are {‘a’, ‘ala’, ‘alala’}. Given the string S, could you help the little cat to write a program to calculate the length of possible prefix-suffix strings of S? (He might thank you by giving your baby a name:)

Input
The input contains a number of test cases. Each test case occupies a single line that contains the string S described above.
Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000.

Output
For each test case, output a single line with integer numbers in increasing order, denoting the possible length of the new baby’s name.

Sample Input
ababcababababcabab
aaaaa
Sample Output
2 4 9 18
1 2 3 4 5

【题解】next值

#include<stdio.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>

#define PI 2*acos(0.0)
#define ll long long
#define INT_MAX 2147483647

using namespace std;
char st[400005]; int next[400005],len,ans[400005],n;
void GetNext(char st[])
{
    int i=0,j=-1; next[0]=-1;
    while (i<=len)
    {
        if (j==-1 || st[i]==st[j])
        {
            i++;j++;
            next[i]=j;
        }
        else
            j=next[j];
    }
    return;
}
int main()
{
    while (scanf("%s",st)>0)
    {
        len=strlen(st);
        GetNext(st);
        //for (int i=0;i<len;i++) cout<<next[i]; cout<<endl;
        int x=next[len-1]; n=1; ans[1]=len;
        while (x!=-1)
        {
            if (st[x]==st[len-1]) ans[++n]=x+1;
            x=next[x];
        }
        for (int i=n;i>0;i--) cout<<ans[i]<<' '; cout<<endl;
    }
    return 0;
}


D
【题解】马拉车+贪心(区将覆盖)

#include<stdio.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define mst(a,b) memset(a,b,sizeof a)
#define N 50000+5
using namespace std;
char s[N],a[2*N]; int len,pal[2*N];
struct data
{
    int l,r;
} qu[2*N];
bool cmp(data a,data b)
{
    if (a.l==b.l) return a.r>b.r;
     else return a.l<b.l;
}
void insert()
{
    mst(a,0);
    int lena=0;
    a[0]='+';
    for (int i=0;i<len;i++)
    {
        a[++lena]='#';
        a[++lena]=s[i];
    }
    a[++lena]='#';
    a[++lena]='-';
    len=lena-1;
    return;
}
void manacher()
{
    insert();
    int mx=0,id;
    for (int i=1;i<=len;i++)
    {
        if (mx>=i) pal[i]=min(mx-i+1,pal[2*id-i]);
         else pal[i]=1;
        while (a[i-pal[i]]==a[i+pal[i]]) pal[i]++;
        if (mx<i+pal[i]-1) mx=i+pal[i]-1,id=i;
    }
    return;
}
int fugai()
{
    int ans=0,far=1;
    for (int i=1;qu[i].l<=1;i++)
     if (qu[i].r>qu[far].r) far=i;
    int i=1;
    while (i<=len)
    {
        ans++;
        int tmp=far;
        for (;qu[i].l<=qu[far].r;i++)
            if (qu[i].r>qu[tmp].r) tmp=i;
        far=tmp;
    }
    return ans;
}
int main()
{
    while (scanf("%s",s)==1)
    {
        len=strlen(s);
        manacher();
        mst(qu,0);
        for (int i=1;i<=len;i++)
        {
            qu[i].l=i-pal[i]+1;
            qu[i].r=i+pal[i]-1;
        }
        sort(qu+1,qu+1+len,cmp);
        printf("%d\n",fugai()-1);
    }
	return 0;
}

参考

E

Your task is, given an integer N, to make a palidrome (word that reads the same when you reverse
it) of length at least N. Any palindrome will do. Easy, isn’t it? That’s what you thought before you
passed it on to your inexperienced team-mate. When the contest is almost over, you find out that
that problem still isn’t solved. The problem with the code is that the strings generated are often not
palindromic. There’s not enough time to start again from scratch or to debug his messy code. Seeing
that the situation is desperate, you decide to simply write some additional code that takes the output
and adds just enough extra characters to it to make it a palindrome and hope for the best. Your
solution should take as its input a string and produce the smallest palindrome that can be formed by
adding zero or more characters at its end.

Input
Input will consist of several lines ending in EOF. Each line will contain a non-empty string made up of
upper case and lower case English letters (‘A’-‘Z’ and ‘a’-‘z’). The length of the string will be less than
or equal to 100,000.

Output
For each line of input, output will consist of exactly one line. It should contain the palindrome formed
by adding the fewest number of extra letters to the end of the corresponding input string.

Sample Input
aaaa
abba
amanaplanacanal
xyz

Sample Output
aaaa
abba
amanaplanacanalpanama
xyzyx

#include<stdio.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>

#define PI 2*acos(0.0)
#define ll long long
#define INT_MAX 2147483647

using namespace std;
char st[100005]; int len;
bool check(int l)
{
    int r=len-1;
    while (l<r && st[l]==st[r])
    {
        l++;
        r--;
    }
    if (l<r) return false; else return true;
}
int main()
{
	while (scanf("%s",st)>0)
    {
        len=strlen(st);
        char e=st[len-1];
        for (int i=0;i<len;i++)
            if (st[i]==e && check(i))
        {
            printf("%s",st);
            for (int j=i-1;j>=0;j--) printf("%c",st[j]);
            printf("\n");
            break;
        }
    }
	return 0;
}

F——Whose sentence is it?

time limit per test2 seconds
memory limit per test256 megabytes

One day, liouzhou_101 got a chat record of Freda and Rainbow. Out of curiosity, he wanted to know which sentences were said by Freda, and which were said by Rainbow. According to his experience, he thought that Freda always said “lala.” at the end of her sentences, while Rainbow always said “miao.” at the beginning of his sentences. For each sentence in the chat record, help liouzhou_101 find whose sentence it is.

Input
The first line of the input contains an integer n (1 ≤ n ≤ 10), number of sentences in the chat record. Each of the next n lines contains a sentence. A sentence is a string that contains only Latin letters (A-Z, a-z), underline (_), comma (,), point (.) and space ( ). Its length doesn’t exceed 100.

Output
For each sentence, output “Freda’s” if the sentence was said by Freda, “Rainbow’s” if the sentence was said by Rainbow, or “OMG>.< I don’t know!” if liouzhou_101 can’t recognize whose sentence it is. He can’t recognize a sentence if it begins with “miao.” and ends with “lala.”, or satisfies neither of the conditions.

Examples
input
5
I will go to play with you lala.
wow, welcome.
miao.lala.
miao.
miao .
output
Freda’s
OMG>.< I don’t know!
OMG>.< I don’t know!
Rainbow’s
OMG>.< I don’t know!

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define mst(a,b) memset(a,b,sizeof a)

#define PI 2*acos(0.0)
#define ll long long
#define INT_MAX 2147483647

using namespace std;
int t,len; char st[1005];
bool checkl()
{
    if (len-5>=0 && st[len-1]=='.' && st[len-2]=='a' && st[len-3]=='l' &&
        st[len-4]=='a' && st[len-5]=='l') return true;
            else return false;
}
bool checkm()
{
    if (len>=5 && st[0]=='m' && st[1]=='i' && st[2]=='a' && st[3]=='o' && st[4]=='.')
        return true;
     else return false;
}
int main()
{
    //IOS
    cin>>t; getchar();
    while (t-->0)
    {
        len=0;
        while ((st[len]=getchar())!='\n' && st[len]!=EOF) len++;
        st[len]='\0';
        //cout<<st<<endl<<endl;
        if ((!checkl() && !checkm()) || (checkl() && checkm())) cout<<"OMG>.< I don't know!"<<endl;
         else if (checkl()) cout<<"Freda's"<<endl;
          else if (checkm()) cout<<"Rainbow's"<<endl;
    }
    return 0;
}

H
【题解】简单AC自动机模板

#include<stdio.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<queue>
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define mst(a,b) memset(a,b,sizeof a)
#define N 1000005
using namespace std;
int trie[N][26],cnt[N],fail[N],pos;
void insert(char* p)
{
    int u=0;
    int len=strlen(p);
    for (int i=0;i<len;i++)
    {
        int v=p[i]-'a';
        if (trie[u][v]==0) trie[u][v]=++pos;
        u=trie[u][v];
    }
    cnt[u]++;
    return;
}
void getfail()
{
    queue <int> q;
    for (int i=0;i<26;i++)
    {
        if (trie[0][i])
        {
            fail[trie[0][i]]=0;
            q.push(trie[0][i]);
        }
    }
    while (!q.empty())
    {
        int cur=q.front();
        q.pop();
        for (int i=0;i<26;i++)
        {
            if (trie[cur][i])
            {
                fail[trie[cur][i]]=trie[fail[cur]][i];
                q.push(trie[cur][i]);
            }
            else
                trie[cur][i]=trie[fail[cur]][i];
        }
    }
    return;
}
int query(char* s)
{
    int cur=0,ans=0,len=strlen(s);
    for (int i=0;i<len;i++)
    {
        cur=trie[cur][s[i]-'a'];
        for (int j=cur;j && cnt[j];j=fail[j])
        {
            ans+=cnt[j];
            cnt[j]=0;
        }
    }
    return ans;
}
int main()
{
    int t,n; char p[N],s[N];
    cin>>t;
    while (t--)
    {
        scanf("%d",&n);
        memset(trie, 0, sizeof(trie));
        memset(cnt, 0, sizeof(cnt));
        fail[0]=pos=0;
        for (int i=1;i<=n;i++)
        {
            scanf("%s",p);
            insert(p);
        }
        getfail();
        scanf("%s",s);
        printf("%d\n",query(s));
    }
    return 0;
}

E—xponential notation

time limit per test2 seconds
memory limit per test256 megabytes

You are given a positive decimal number x.

Your task is to convert it to the “simple exponential notation”.

Let x = a·10b, where 1 ≤ a < 10, then in general case the “simple exponential notation” looks like “aEb”. If b equals to zero, the part “Eb” should be skipped. If a is an integer, it should be written without decimal point. Also there should not be extra zeroes in a and b.

Input
The only line contains the positive decimal number x. The length of the line will not exceed 106. Note that you are given too large number, so you can’t use standard built-in data types “float”, “double” and other.

Output
Print the only line — the “simple exponential notation” of the given number x.

Examples
input
16
output
1.6E1
input
01.23400
output
1.234
input
.100
output
1E-1
input
100.
output
1E2

#include<stdio.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>

#define PI 2*acos(0.0)
#define ll long long
#define INT_MAX 2147483647

using namespace std;
char st[1000005];
int main()
{
    cin>>st;
    int x=0,z=0,len=strlen(st),y=len-1;
    while (x<len && (st[x]=='0' || st[x]=='.')) x++;
    if (x==len)
    {
        cout<<0<<endl;
        return 0;
    }
    cout<<st[x];
    while (y>=0 && (st[y]=='0' || st[y]=='.')) y--;
    while (z<len && st[z]!='.') z++;
    if (y!=x)
    {
        cout<<'.';
        for (int i=x+1; i<=y; i++)
            if (st[i]!='.')
                cout<<st[i];
    }
    if (z!=x+1)
    {
        cout<<'E';
        //if (z==len) z--;
        if (x<z) cout<<z-x-1;
         else cout<<'-'<<x-z;
    }
    //cout<<endl<<x<<' '<<y<<' '<<z<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值