[POI 2012]A Horrible Poem(字符串Hash)

本文介绍了一种解决字符串中子串最小循环节长度问题的方法。利用哈希表和最大公约数(GCD)特性,通过枚举和验证,实现了高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

http://main.edu.pl/en/archive/oi/19/okr

题目大意

给出一个字符串,多次询问其中一个子串 [L,R] 的最小循环节长度。

思路

假设 Ri=L(S[i]==x) 表示区间 [L,R] 里字母 x 的出现次数。

假设最小循环节长度为 t ,则RL+1t(最小循环节的出现次数)是 gcdt{Ri=L(S[i]==t)} 的约数。

因此我们可以枚举 gcdt{Ri=L(S[i]==t)} 的约数,得到枚举出的最小循环节的长度,这样枚举最小循环节的长度,枚举次数会很少。一个合法的循环节长度可以取 l ,当且仅当[L,Rl]部分和 [L+l,R] 相同,这个可以自行yy下为啥是正确的。。。详细证明不好证。。。这样的话,我们在枚举了最小循环节的长度后就可以用hash来 O(1) 判断所枚举的循环节长度是否是合法的了

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 510000
#define MOD 1000000009

using namespace std;

typedef long long int LL;

char s[MAXN];
LL hash[MAXN],pow[MAXN];
int n,q;
int sum[MAXN][26];

int gcd(int a,int b)
{
    if(!b) return a;
    return gcd(b,a%b);
}

bool check(int L1,int R1,int L2,int R2)
{
    LL hash1=((hash[R1]-pow[R1-L1+1]*hash[L1-1]%MOD)%MOD+MOD)%MOD;
    LL hash2=((hash[R2]-pow[R2-L2+1]*hash[L2-1]%MOD)%MOD+MOD)%MOD;
    return hash1==hash2;
}

int main()
{
    scanf("%d",&n);
    scanf("%s",s+1);
    pow[0]=1;
    for(int i=1;i<=n;i++)
        pow[i]=pow[i-1]*30007%MOD;
    for(int i=1;i<=n;i++)
        hash[i]=(hash[i-1]*30007%MOD+s[i]-'a'+1)%MOD;
    for(int i=1;i<=n;i++)
        for(int alpha=0;alpha<26;alpha++)
        {
            sum[i][alpha]=sum[i-1][alpha];
            sum[i][alpha]+=((s[i]-'a')==alpha);
        }
    scanf("%d",&q);
    while(q--)
    {
        int L,R,ans=0;
        scanf("%d%d",&L,&R);
        int GCD=0,len=R-L+1;
        for(int alpha=0;alpha<26;alpha++)
            GCD=gcd(GCD,sum[R][alpha]-sum[L-1][alpha]);
        for(int i=1;i*i<=GCD;i++)
        {
            if(check(L,R-len/i,L+len/i,R)) ans=max(ans,i);
            if(check(L,R-len/(GCD/i),L+len/(GCD/i),R)) ans=max(ans,GCD/i);
        }
        printf("%d\n",len/ans);
    }
    return 0;
}
### 如何正确使用 poi-tl 集合输出字符串 在 Java 中,`poi-tl` 是一个用于操作 Microsoft Word 文档的强大工具库。它允许开发者通过模板方式快速生成复杂的 Word 文件。当涉及到集合输出字符串时,通常会结合 `List` 或其他集合类型的对象来动态填充模板中的占位符。 以下是关于如何正确使用 `poi-tl` 处理集合并输出字符串的具体方法: #### 数据绑定机制 `poi-tl` 支持将 Java 对象映射到 Word 模板中的占位符上。如果需要处理集合类型的数据,则可以通过指定特定的语法结构实现循环渲染。例如,在模板中可以定义如下占位符 `${listItem}` 来表示列表项的内容[^2]。 #### 示例代码 下面是一个完整的示例,展示如何利用 `poi-tl` 将集合转换为字符串形式,并将其嵌入到 Word 文档中。 ```java import cn.afterturn.easypoi.word.WordExportUtil; import org.apache.poi.xwpf.usermodel.XWPFDocument; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class PoiTlExample { public static void main(String[] args) throws Exception { // 创建数据模型 Map<String, Object> dataMap = new HashMap<>(); List<String> stringList = new ArrayList<>(); stringList.add("Apple"); stringList.add("Banana"); stringList.add("Cherry"); // 绑定集合到 map dataMap.put("fruits", stringList); // 加载模板文件 XWPFDocument document = WordExportUtil.exportWord("template.docx", dataMap); // 输出生成的文档 try (FileOutputStream fos = new FileOutputStream("output.docx")) { document.write(fos); } } } ``` 上述代码片段展示了如何创建一个简单的 Word 文档模板,并通过传递包含字符串集合的对象完成替换工作。其中的关键在于确保模板内的变量名(如 `${fruits}`)与实际传入的地图键相匹配。 #### 图片标签注意事项 对于涉及图片的情况需要注意的是,虽然普通的 HTML 标签可能不会被完全支持,但是特殊标记如 `{{@logo}}` 可用来指示程序查找对应的图像资源路径[^3]。因此,若需同时插入文字和图形内容,应遵循此约定设置好关联字段及其值。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值