zoukankan      html  css  js  c++  java
  • (2019.9.5~2019.9.11)补题汇总(字符串相关)

    [1] [HDU3374]String Problem

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5489 Accepted Submission(s): 2258

    Problem Description

    Give you a string with length N, you can generate N strings by left shifts. For example let consider the string “SKYLONG”, we can generate seven strings:
    String Rank
    SKYLONG 1
    KYLONGS 2
    YLONGSK 3
    LONGSKY 4
    ONGSKYL 5
    NGSKYLO 6
    GSKYLON 7
    and lexicographically first of them is GSKYLON, lexicographically last is YLONGSK, both of them appear only once.
    Your task is easy, calculate the lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), its times, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.

    Input

    Each line contains one line the string S with length N (N <= 1000000) formed by lower case letters.

    Output

    Output four integers separated by one space, lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), the string’s times in the N generated strings, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.

    Sample Input

    abcder
    aaaaaa
    ababab
    

    Sample Output

    1 1 6 1
    1 6 1 6
    1 3 2 3
    

    解题思路

    挺综合的一道题(我还是太菜了2333)。需要求循环字符串中字典序最小和最大的并输出其出现的次数。求字符串用到最大最小表示法(图示更新中ing......),统计出现次数正好可以用到KMP中记录next(prefix)数组。刚开始用的是纯模拟优化了一下直接wa了。。。。。。后来不读一下全是班子,emm......

    代码样例(转自ChenJr

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2000005;
    
    char s[maxn];
    int nextt[maxn];
    
    void get_next(char *a, int len)
    { //求解next数组板子
        int i = 0, j = nextt[0] = -1;
        while (i < len)
        {
            while (j != -1 && a[i] != a[j])
                j = nextt[j];
            nextt[++i] = ++j;
        }
    }
    
    int get_minn(char *a, int len)
    { //最小表示法板子
        int i = 0, j = 1;
        for (int i = 0; i < len; i++)
        {
            s[i + len] = s[i];
        }
        while (i < len && j < len)
        {
            int k;
            for (k = 0; k < len && a[k + i] == a[k + j]; k++)
                ;
            if (k == len)
                break;
            if (a[k + i] > a[k + j])
            {
                i = i + k + 1;
                if (i == j)
                    i++;
            }
            else
            {
                j = j + k + 1;
                if (i == j)
                    j++;
            }
        }
        return min(i, j);
    }
    
    int get_maxx(char *a, int len)
    { //最大表示法板子
        int i = 0, j = 1;
        for (int i = 0; i < len; i++)
        {
            s[i + len] = s[i];
        }
        while (i < len && j < len)
        {
            int k;
            for (k = 0; k < len && a[k + i] == a[k + j]; k++)
                ;
            if (k == len)
                break;
            if (a[k + i] < a[k + j])
            {
                i = i + k + 1;
                if (i == j)
                    i++;
            }
            else
            {
                j = j + k + 1;
                if (i == j)
                    j++;
            }
        }
        return min(i, j);
    }
    
    int main()
    {
        while (~scanf("%s", s))
        {
            int len = strlen(s);
            memset(nextt, 0, sizeof(nextt));
            get_next(s, len);
            int minn = get_minn(s, len);
            int maxx = get_maxx(s, len);
            int tmp = nextt[len];
            if (len % (len - tmp) != 0)
            {
                cout << minn + 1 << " 1 " << maxx + 1 << " 1" << endl;
            }
            else
            {
                cout << minn + 1 << " " << len / (len - tmp) << " " << maxx + 1 << " " << len / (len - tmp) << endl;
            }
        }
        return 0;
    }
    

    [2] [HDU-6229]string matching

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1708 Accepted Submission(s): 706

    Problem Description

    String matching is a common type of problem in computer science. One string matching problem is as following:

    Given a string s[0…len−1], please calculate the length of the longest common prefix of s[i…len−1] and s[0…len−1] for each i>0.

    I believe everyone can do it by brute force.
    The pseudo code of the brute force approach is as the following:

    img

    We are wondering, for any given string, what is the number of compare operations invoked if we use the above algorithm. Please tell us the answer before we attempt to run this algorithm.

    Input

    The first line contains an integer T, denoting the number of test cases.
    Each test case contains one string in a line consisting of printable ASCII characters except space.

    * 1≤T≤30

    * string length ≤106 for every string

    Output

    For each test, print an integer in one line indicating the number of compare operations invoked if we run the algorithm in the statement against the input string.

    Sample Input

    3
    _Happy_New_Year_
    ywwyww
    zjczzzjczjczzzjc
    

    Sample Output

    17
    7
    32
    

    解题思路

    扩展KMP,一开始以为是ac自动机,结果gg。利用扩展KMP求出每一位的最长字符子串,如果这一位的位置加上它的子串长没用超过字符串的最后一位,在统计时还要加上一次比较次数。

    *扩展KMP参考拓展kmp算法总结

    代码样例

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int K=1000005;
    int nt[K],extand[K];
    char S[K],T[K];
    int a[K];
    ll ans;
    
    void Getnext(char *T,int *next)
    {
        int len=strlen(T),a=0;
        next[0]=len;
        while(a<len-1 && T[a]==T[a+1]) a++;
        next[1]=a;
        a=1;
        for(int k=2; k<len; k++)
        {
            int p=a+next[a]-1,L=next[k-a];
            if( (k-1)+L >= p)
            {
                int j = (p-k+1)>0 ? (p-k+1) : 0;
                while(k+j<len && T[k+j]==T[j]) j++;
                next[k]=j;
                a=k;
            }
            else
                next[k]=L;
        }
    }
    
    void GetExtand(char *S,char *T,int *next)
    {
        Getnext(T,next);
        int slen=strlen(S),tlen=strlen(T),a=0;
        int MinLen = slen < tlen ? slen : tlen;
        while(a<MinLen && S[a]==T[a]) a++;
        extand[0]=a;
        a=0;
        for(int k=1; k<slen; k++)
        {
            int p=a+extand[a]-1, L=next[k-a];
            if( (k-1)+L >= p)
            {
                int j= (p-k+1) > 0 ? (p-k+1) : 0;
                while(k+j<slen && j<tlen && S[k+j]==T[j]) j++;
                extand[k]=j;
                a=k;
            }
            else
                extand[k]=L;
        }
    }
    
    int main(void)
    {
    	int tl;scanf("%lld",&tl);
        while(tl--)
        {
        	memset(nt,0,sizeof(nt));
        	memset(extand,0,sizeof(extand));
        	memset(a,0,sizeof(a));
    		scanf("%s",S);
        	ans = 0;
        	strcpy(T,S);
            GetExtand(S,T,nt);
            int len = strlen(T);
            queue<int> id;
    		ans = 0;
    		ans+=len-1;
    		for(int i=1; i<len; i++) {
    			if(nt[i]!=0) {
    				ans+=nt[i];
    				if(i+nt[i]>=len)ans--;
    			}
    		}
    		printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Spark基础知识详解
    jenkins shared library【demo】
    反if的活动
    开发工具vscode
    【火狐】查看和切换 本地服务 与 全球服务
    java【Socket】【上传下载文件】
    Android【照片备份】【折腾方案1】
    total commander【删除重复文件】
    jenkins【插件】【优先级】
    Android【照片备份】【折腾方案2】
  • 原文地址:https://www.cnblogs.com/cafu-chino/p/11759923.html
Copyright © 2011-2022 走看看