17999 Light-bot 模拟 + kmp求循环节

http://acm.scau.edu.cn:8000/uoj/mainMenu.html

17999 Light-bot

时间限制:1000MS  内存限制:65535K

提交次数:0 通过次数:0

题型: 编程题   语言: 不限定

Description

I (you needn‘t know
who am "I".) am currently playing a game called
"Light-bot". In the game, the "Light-bot" is controlled

by a program. The
program includes:

(1) The main
procedure. The main procedure is the entrance of the program, same as the
"main" in C/C++.

(2) Sub procedure
#1. Sub procedure No.1.

(3) Sub procedure
#2. Sub procedure No.2.

Note: If a sub
procedure ends, it will return to the command next to it‘s calling place.

Here, we suggest
that an alphabetical letter stands for an ACTION COMMAND excluding ‘P’ and ‘p’.

So,
"Light-bot" will begin executing from the first command in the main
procedure. Once it meets with a letter ‘P’, it will call sub

procedure #1, while
a letter ‘p’ indicates to call sub procedure #2. The main procedure, procedure
#1 and procedure #2 can call

procedure #1 or
procedure #2 freely. It means that recursive calls are possible.

Now, I just want to
know given a program, what’s the Nth ACTION COMMAND light-bot will execute.

输入格式

The first line of
the input contains an integer T (T <= 1000), indicating there are T cases in
the input file.

For each test case,
the first line is the main procedure. The second one is sub procedure #1 and
the last is sub procedure #2. Each

procedure ends with
a ‘#’ sign, which is not considered a command. The length of a part will not
exceed 10.

And on the next
line, there is one integer n (1 <= n <= 108), indicates the
order I ask. It is GUARANTEED that there must be an ACTION COMMAND

fitting the requirement.

Please see the
example for more details.

输出格式

For each case,
print one line, the ACTION COMMAND letter that fits the description.

输入样例

4

ABCDP#

pEFG#

HIJK#

4

ABCDP#

pEFG#

HIJK#

5

ABCDP#

pEFG#

HIJK#

9

ABCDP#

EFGHP#

#

12

输出样例

D

H

E

H

来源

Lrc_seraph

首先因为其最大的数量是1000(不循环的话)

那么我可以暴力模拟2000次,然后得到一个序列。这个序列的后边肯定是循环的了。

就是XXXXABCABCABC....这样。

然后可以反向kmp一次,求循环节的时候,要从第100项开始,

原因是:

1、第100项开始,求到的循环节长度是一样的,

2、防止AAAA这些假循环节的干扰。

坑了我很久的就是模拟的时候,我模拟到up步,但是取了等号,模拟了UP + 1步。然后一直wa

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
char str[4][20];
char Ma[20];
int len[5];
int lenMa;
const int up = 2000 + 20;
char all[up + 20];
int lenall = 0;
char sub[up + 20];
int lensub = 0;
void dfs(int now, int cur) {
    if (lenall >= up) return;
    for (int i = cur; i <= len[now] && lenall < up; ++i) {
        if (str[now][i] == ‘P‘) {
            dfs(0, 1);
        } else if (str[now][i] == ‘p‘) {
            dfs(1, 1);
        } else all[++lenall] = str[now][i];
    }
}
int tonext[up + 20];
void kmp() {
    int i = 1, j = 0;
    tonext[1] = 0;
    while (i <= lensub) {
        if (j == 0 || sub[i] == sub[j]) {
            tonext[++i] = ++j;
        } else j = tonext[j];
    }
}
void work() {
    scanf("%s", Ma + 1);
    for (int i = 0; i <= 1; ++i) {
        scanf("%s", str[i] + 1);
        len[i] = strlen(str[i] + 1);
        len[i]--;
    }
    lenMa = strlen(Ma + 1);
    lenMa--;
    lenall = 0;
    for (int i = 1; i <= lenMa && lenall < up; ++i) { //这个up不能去等号
        if (Ma[i] == ‘P‘) {
            dfs(0, 1);
        } else if (Ma[i] == ‘p‘) {
            dfs(1, 1);
        } else {
            all[++lenall] = Ma[i];
        }
    }
    all[lenall + 1] = ‘\0‘;
    int val;
    scanf("%d", &val);
    if (val <= up) {
        printf("%c\n", all[val]);
        return;
    }
    lensub = 0;
    for (int i = lenall; i >= 1; --i) {
        sub[++lensub] = all[i];
    }
    sub[lensub + 1] = ‘\0‘;
    kmp();
//    cout << sub + 1 << endl;
    int cir = 0;
//        cout << all + 1 << endl;
    for (int i = 1000 + 20; i <= lensub; ++i) {
        if (tonext[i + 1] == 1) continue;
        int t = i - (tonext[i + 1] - 1);
        if (i % t == 0) {
            cir = t;
//            cout << i << endl;
            break;
        }
    }
//    cout << cir << endl;
    if (cir == 0) while(1);
    int left = val - up;

    left %= cir;
    if (left == 0) left = cir;
    int point = lenall - cir + left;
    printf("%c\n", all[point]);

}

int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    int t;
    scanf("%d", &t);
    while (t--) work();
    return 0;
}

时间: 2024-12-16 19:20:41

17999 Light-bot 模拟 + kmp求循环节的相关文章

HDU 3746 Cyclic Nacklace(KMP求循环节)

Description CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, without any surprise, there are only 99.9 yuan left. he is too distressed and thinking about how to tide over the last days. Being inspir

HDU - 3746 Cyclic Nacklace (KMP求循环节)

Description CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, without any surprise, there are only 99.9 yuan left. he is too distressed and thinking about how to tide over the last days. Being inspir

hdu3746 kmp求循环节

CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, without any surprise, there are only 99.9 yuan left. he is too distressed and thinking about how to tide over the last days. Being inspired by the en

【HDU 3746】Simpsons’ Hidden Talents(KMP求循环节)

求next数组,(一般有两种,求循环节用的见代码)求出循环节的长度. #include <cstdio> #define N 100005 int n,next[N]; char s[N]; int main(){ scanf("%d",&n); while(n--){ scanf("%s",s); int i=0,k=-1; next[0]=k; while(s[i]){ if(k==-1||s[i]==s[k]) { i++; k++; ne

HDU3746 Cyclic Nacklace KMP求循环节

HDU3746给定一个字符串,求:在该字符串末尾最少补充多少个字符,可以使得这个字符串获得周期性. 周期性指存在一个子串,使得该字符串可以正好分解成若干个这个子串(数量要大于1). Input 第一行是一个整数 T ( 0<T<=100 ) 代表测试数据的组数. 之后T行每行一个字符串,由小写字母组成,字符串的长度3<=L<=100000. Output 每组数据输出一行结果. Sample Input 3 AAA ABCA ABCDE Sample Output 0 2 5 本题

hdu 3746 kmp求循环节

题意就是将所给的字符串变成多个完整的循环(至少两个),然后给出最少需要添加的字符数. http://www.cnblogs.com/wuyiqi/archive/2012/01/06/2314078.html 1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 const int MAXN=10

区间DP+next求循环节 uva 6876

1 // 区间DP+next求循环节 uva 6876 2 // 题意:化简字符串 并表示出来 3 // 思路:dp[i][j]表示 i到j的最小长度 4 // 分成两部分 再求一个循环节 5 6 #include <iostream> 7 #include <algorithm> 8 #include <cstring> 9 #include <cstdio> 10 #include <vector> 11 #include <cmath

HDU - 4333 Revolving Digits(拓展kmp+最小循环节)

1.给一个数字字符串s,可以把它的最后一个字符放到最前面变为另一个数字,直到又变为原来的s.求这个过程中比原来的数字小的.相等的.大的数字各有多少. 例如:字符串123,变换过程:123 -> 312 -> 231 -> 123 因为:312>123, 231>123, 123=123 所以答案是:0 1 2 2.令str1=s,str2=s+s,然后str1作为子串,str2作为主串,进行扩展kmp求出str2[i...len2-1]与str1[0...len1-1]的最长

hdu4333 Revolving Digits(扩展kmp+kmp最小循环节)

题目链接:点击打开链接 题意描述:给定一个字符串,可以把字符串的后x位移到字符串前面组成一个新的字符串?问对于所有的新组成的字符串中去掉重复的之后,比原串小的个数,等于的个数,大于的个数? 解题思路:扩展KMP(next1[i]数组含义:x[i···len-1]与x[0···len-1]的最长公共前缀) 分析:首先我们把字符串s复制一遍接到原字符串后面形成ss,这样在ss中以i(i>=0&&i<len)为起点的长度为len的字符串就是所有可能的新字符串: 讲到这里,问题转变为在