1. 程式人生 > >Jzoj P5912 VanUSee___博弈+KMP

Jzoj P5912 VanUSee___博弈+KMP

題目大意:

給定兩個串 S 和 T,S>=T|S| >= |T|。 兩個人博弈,每一輪操作,兩人先後可以刪掉 S 的首位或者末位。 當操作以後的串的長度等於T|T|時,遊戲停止。 如果停止時 SS 剩下的串=T=T,則後手獲勝,否則先手獲勝。 問兩人均採取最優策略下誰贏

1<=t<=101<=t<=10 1<=T<=S<=1000001<=|T|<=|S|<=100000

分析:

考慮簡化表示狀態 設左邊已經刪掉了 L 個字元,右邊已經刪掉了 R 個字元 那麼用 R-L 來表示當前狀態,可以用 KMP 求出有哪些目標狀態 一開始 R-L 為 0,每一次操作可以讓它+1 或者-1,雙方輪流操作,總共|S|-|T|次操 作,雙方都用最優策略看最後是否能到達目標狀態 顯然所有的目標狀態奇偶性相同 當|S|-|T|為奇數時,最後一次操作是先手做,它肯定往不是目標狀態走,那麼一個 位置在最後一次操作前是目標狀態當且僅當它+1 它-1 都是目標狀態 現在就全部轉化成|S|-|T|為偶數的情況 假如 0 是目標狀態,那麼顯然後手會贏,因為無論先手往哪裡走後手都可以把他拉 回來 如果 0 不是,並且-2 和 2 不全是,那麼先手一定會朝不是的那一邊走,後手無論 如何都沒有辦法將它拉回到是的那一邊了 因此後手會贏當且僅當 0 是目標狀態或者-2 和 2 都是目標狀態 否則都是先手贏 利用KMP求出目標狀態的所有位置然後判斷。

程式碼:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <cmath>
#define N 100005

using namespace std;

int begind[2][N], next[N], Q;
char S[N], T[N];

int main() 
{
	freopen("vanusee.in", "r", stdin);
	freopen("vanusee.out", "w", stdout);
	scanf("%d", &Q);
	while (Q--)
	{
	   scanf("%s", S + 1); int len1 = strlen(S + 1);
	   scanf("%s", T + 1); int len2 = strlen(T + 1);
	   memset(begind, 0, sizeof(begind));
	   int j = 0, tot = 0, orz = (len1 - len2) % 2;
	   for (int i = 2; i <= len2; i++)
	   {
	   	    while (j && T[i] != T[j + 1]) j = next[j]; 
			if (T[i] == T[j + 1]) j++; 
			next[i] = j; 
 	   }
 	   j = 0;
 	   for (int i = 1; i <= len1; i++)
 	   {
	        while (j && S[i] != T[j + 1]) j = next[j];
			if (S[i] == T[j + 1]) j++;
			if (j == len2) 
			    begind[orz][++tot] = (len1 - i) - (i - len2), j = next[j];
	   }
	   if (orz)  
	   {
	   	    sort(begind[orz] + 1, begind[orz] + tot + 1);
	        for (int i = 2; i <= tot; i++)
	   	         if (begind[orz][i] - begind[orz][i - 1] == 2) begind[orz][i - 1] = begind[orz][i] - 1;
	   	    tot--;
	   	}
		bool xx = 0, yy = 0, xy = 0;
		for (int i = 1; i <= tot; i++)
	   	{
	   		 if (begind[orz][i] == 2) xx = 1;
	   		 if (begind[orz][i] == -2) yy = 1;
	   		 if (begind[orz][i] == 0) xy = 1;
		}
			if (xy || (xx && yy)) printf("pty\n"); else printf("cqf\n");
	}
	return 0;
}