码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-11-11 00:18:18      阅读:304      评论:0      收藏:0      [点我收藏+]

标签:++   contains   c++   sync   来源   ble   std   pos   control   

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;
}
View Code

 

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

标签:++   contains   c++   sync   来源   ble   std   pos   control   

原文地址:http://www.cnblogs.com/liuweimingcprogram/p/6052627.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!