BJ模拟 Circle of Stones【KMP】

本文介绍了一种通过KMP算法解决美丽石头环问题的方法。该问题要求确定在拿走一定数量的连续石头后,剩余石头组成的环是否美丽(即相邻石头颜色不同)。文章详细解释了如何将问题转化为寻找特定子区间的过程,并利用KMP算法进行高效求解。
题目描述:

桌子上有 n 个石头围成一个环。每个石头都有一种颜色。每种颜色可以由小写英文字母表示,所以总共有26种颜色。不同的石头可能有相同的颜色。

如果每一对相邻的石头都是不同颜色的,则称这 n 个石头构成的环是美丽的。两个石头是相邻的充要条件是这两个石头中间没有其它石头。例如:1号和2号是相邻的,2号和3号是相邻的,……,n号和1号是相邻的。

现在,你可以从这 n 个石头中拿走一段连续的石头(可以为空),且你只能拿一次。

你的任务是对于每个 k(0≤k≤n−1) ,判断是否存在一种取石头的方案,使得在拿走 k 个连续的石头后,剩下的 n−k 个石头构成的环是美丽的。

解题思路:

相邻位置相同把可以剩下的位置变为若干区间,我们对于每个区间单独考虑:

判断合法的k等价于判断是否存在长度为n-k的子区间使得两端不同,考虑如果不合法,则又等价于任意s[i]=s[i+n-k-1],即为存在周期n-k-1(不是循环)。

周期和border相对应,利用KMP寻找border,时间复杂度O(n)。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2000005;
int T,n,vt,nxt[N],ans[N],vis[N];
char s[N],t[N];
void work(int l,int r)
{
    int len=0;
    for(int i=l;i<=r;i++)t[++len]=s[i];
    for(int i=2,j=0;i<=len;i++)
    {
        while(j&&t[i]!=t[j+1])j=nxt[j];
        if(t[j+1]==t[i])j++;
        nxt[i]=j;
    }
    ++vt;
    for(int i=nxt[len];i;i=nxt[i])vis[len-i]=vt;
    for(int i=0;i<len&&i<n;i++)if(vis[i]!=vt)ans[n-i-1]=1;
}
void solve()
{
    memset(ans,0,sizeof(ans));
    n=strlen(s+1);
    for(int i=n+1;i<=2*n;i++)s[i]=s[i-n];
    for(int i=1,j=1;i<=2*n;i=++j)
    {
        while(j<2*n&&s[j]!=s[j+1])++j;
        work(i,j);
    }
    printf("Case %d: ",++T);
    for(int i=0;i<n;i++) putchar('0'+ans[i]);
    putchar('\n');
}
int main()
{
    //freopen("lx.in","r",stdin);
    while(scanf("%s",s+1)!=EOF)solve();
    return 0;
}
To solve the problem of finding the minimum number of 180 - degree rotations of adjacent 2x2 blocks to rearrange two - row runic stones from an initial state to a target state, we can use a breadth - first search (BFS) algorithm. The following is the Python code implementation: ```python from collections import deque # Function to rotate a 2x2 block def rotate_2x2(state, i, j): new_state = [list(row) for row in state] new_state[i][j], new_state[i + 1][j], new_state[i][j + 1], new_state[i + 1][j + 1] = \ new_state[i + 1][j + 1], new_state[i][j + 1], new_state[i + 1][j], new_state[i][j] return tuple(tuple(row) for row in new_state) # Function to get all possible next states def get_next_states(state): n = len(state[0]) next_states = [] for i in range(1): for j in range(n - 1): next_state = rotate_2x2(state, i, j) next_states.append(next_state) return next_states # BFS function def min_rotations(initial_state, target_state): initial_state = tuple(tuple(row) for row in initial_state) target_state = tuple(tuple(row) for row in target_state) queue = deque([(initial_state, 0)]) visited = set([initial_state]) while queue: current_state, rotations = queue.popleft() if current_state == target_state: return rotations for next_state in get_next_states(current_state): if next_state not in visited: visited.add(next_state) queue.append((next_state, rotations + 1)) return -1 # Example usage initial = [[1, 2, 3], [4, 5, 6]] target = [[3, 2, 1], [6, 5, 4]] print(min_rotations(initial, target)) ``` In this code: 1. The `rotate_2x2` function takes a state and the position `(i, j)` of the top - left corner of a 2x2 block and returns the state after rotating that block by 180 degrees. 2. The `get_next_states` function generates all possible states that can be obtained by rotating a 2x2 block in the current state. 3. The `min_rotations` function uses BFS to explore all possible states starting from the initial state. It keeps track of the number of rotations and the states that have been visited. If the target state is reached, it returns the number of rotations. If there is no way to reach the target state, it returns -1.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值