UVa455周期串(Periodic Strings)

这题有点意思:
1.我设计了伪代码
k=1
while (k<len):
s1=s.substr(k-1,k)
for i=0 to len-1:
if(s1 != s.substr(i*k+k,k)):
isfind=false
break

if(isfind) break;
k++

于是基于以上设计,代码如下:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin>>n;
	while(n--){
		string s;
		cin>>s;
		int len=s.length();
		int k=1;
		bool isfind=true;
		while(k<len){
			isfind=true;
			string s1=s.substr(0,k);
			for(int i=0;i<len;i++){
				if(s1  != s.substr(k*i+k,k)){
					isfind=false;
					break;
				}					
			}
			if(isfind) break;
			else k++;
		}
		cout<<k<<endl;
	}
	return 0;
}

结果错了,连测试用例都没有正确输出!

2.偷了个懒,丢给AI帮我分析哪里逻辑错了

错误1:子串起始位置错误

当 i = 0 时,k*i + k = k,即从第 k 个字符开始取子串,跳过了第一个周期(本应比较第2、3…个周期)。

当 i = 1 时,起始位置为 2k,依此类推。

但由于循环条件 i < len,当 k 较小时,i 会一直增加到接近 len,导致 k*i + k 远超字符串长度,substr 会抛出异常(或返回空串),使比较永远失败。

错误2:越界与遗漏比较

正确的做法应该是:从第 k 个字符开始,每隔 k 取一个子串,共取 len/k - 1 次(因为第一个周期已经作为模板)。

你的循环次数和索引计算都不符合这个逻辑,最终导致即使字符串具有周期 k,也会被判为假。
按照建议我修改了自己的代码如下:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin>>n;
	while(n--){
		string s;
		cin>>s;
		int len=s.length();
		int k=1;
		bool isfind=true;
		while(k<len){
			isfind=true;
			string s1=s.substr(0,k);
			for(int i=1;i*k<len;i++){
				if(s1 != s.substr(k*i,k)){
					isfind=false;
					break;
				}					
			}
			if(isfind) break;
			else k++;
		}
		cout<<k<<endl;
		if(n) cout<<endl;
	}
	return 0;
}

过了,然而rank排名在7615!
3.叫AI给我分析如何进行优化,于是:

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    while (n--) {
        string s;
        cin >> s;
        int len = s.size();
        int period = len;  // 默认周期为全长
        
        // 只检查 len 的因数
        for (int k = 1; k <= len / 2; ++k) {
            if (len % k != 0) continue;  // 长度不能整除,不可能为周期
            bool ok = true;
            for (int i = k; i < len; ++i) {
                if (s[i] != s[i % k]) {
                    ok = false;
                    break;
                }
            }
            if (ok) {
                period = k;
                break;
            }
        }
        cout << period << "\n";
        if (n) cout << "\n";
    }
    return 0;
}

这样rank排名居然是7616!
我感觉上了一个当,然后继续进行追问如何优化,结果我看使用了KMP算法——

#include <stdio.h>
#include <string.h>

int main() {
    int n, len, i, j, period;
    char s[100];
    scanf("%d", &n);
    while (n--) {
        scanf("%s", s);
        len = strlen(s);
        // 计算 KMP 的 next 数组
        int next[100] = {0};
        for (i = 1, j = 0; s[i]; i++) {
            while (j > 0 && s[i] != s[j]) j = next[j-1];
            if (s[i] == s[j]) j++;
            next[i] = j;
        }
        period = len - next[len-1];
        if (len % period != 0) period = len;
        printf("%d\n", period);
        if (n) printf("\n");
    }
    return 0;
}

然而系统排名仍然是7616!

试了好几遍,系统给我的邮件让我很吃惊,真是简洁和友好!
图片

也不用纠结了,这是一道简单题而已~

posted @ 2026-06-04 10:51  qiannong  阅读(21)  评论(0)    收藏  举报