地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6194

题目:

string string string

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 486    Accepted Submission(s): 125

Problem Description
Uncle Mao is a wonderful ACMER. One day he met an easy problem, but Uncle Mao was so lazy that he left the problem to you. I hope you can give him a solution.
Given a string s, we define a substring that happens exactly k times as an important string, and you need to find out how many substrings which are important strings.
 
Input
The first line contains an integer T (T≤100) implying the number of test cases.
For each test case, there are two lines:
the first line contains an integer k (k≥1) which is described above;
the second line contain a string s (length(s)≤105).
It's guaranteed that ∑length(s)≤2∗106.
 
Output
For each test case, print the number of the important substrings in a line.
 
Sample Input
2
2
abcabc
3
abcabcabcabc
 
Sample Output
6
9
 
Source
   
思路:
  sam会卡指针版的代码,不明白卡这么点内存有什么意思。
  后缀自动机做法:建立sam后,统计出cnt数组,这一步要拓扑排序后倒着dp。
  后缀数组做法:用f[i][j]表示height(i,j)的区间最小值,然后滑动大小为k的窗口,则贡献是max(0,f[i][j]-max(height[i-1],height[j+1]) )
后缀自动机做法:
 #include <bits/stdc++.h>

 using namespace std;

 char ss[];
int ans; struct SAM
{
static const int MAXN = <<;//大小为字符串长度两倍
static const int LetterSize = ; int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN];
int sum[MAXN], tp[MAXN], cnt[MAXN]; //sum,tp用于拓扑排序,tp为排序后的数组 void init( void)
{
last = tot = ;
len[] = ;
memset(ch,,sizeof ch);
memset(fa,,sizeof fa);
memset(cnt,,sizeof cnt);
} void add( int x)
{
int p = last, np = last = ++tot;
len[np] = len[p] + , cnt[last] = ;
while( p && !ch[p][x]) ch[p][x] = np, p = fa[p];
if( p == )
fa[np] = ;
else
{
int q = ch[p][x];
if( len[q] == len[p] + )
fa[np] = q;
else
{
int nq = ++tot;
memcpy( ch[nq], ch[q], sizeof ch[q]);
len[nq] = len[p] + , fa[nq] = fa[q], fa[q] = fa[np] = nq;
while( p && ch[p][x] == q) ch[p][x] = nq, p = fa[p];
}
}
} void toposort( void)
{
for(int i = ; i <= len[last]; i++) sum[i] = ;
for(int i = ; i <= tot; i++) sum[len[i]]++;
for(int i = ; i <= len[last]; i++) sum[i] += sum[i-];
for(int i = ; i <= tot; i++) tp[sum[len[i]]--] = i;
}
} sam; int main(void)
{
//freopen("in.acm","r",stdin);
int t,k;cin>>t;
while(t--)
{
ans=;
sam.init();
scanf("%d%s",&k,ss);
for(int i=,len=strlen(ss);i<len;i++) sam.add(ss[i]-'a');
sam.toposort();
for(int i=sam.tot;i;i--)
{
int p=sam.tp[i],fp=sam.fa[p];
sam.cnt[fp]+=sam.cnt[p];
if(sam.cnt[p]==k)
ans+=sam.len[p]-sam.len[fp];
}
printf("%d\n",ans);
} return ;
}

后缀数组做法:

 #include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <iostream>
const int N = ;
int sa[N],s[N],wa[N], wb[N], ws[N], wv[N];
int rank[N], height[N];
char ss[N];
bool cmp(int r[], int a, int b, int l)
{
return r[a] == r[b] && r[a+l] == r[b+l];
} void da(int r[], int sa[], int n, int m)
{
int i, j, p, *x = wa, *y = wb;
for (i = ; i < m; ++i) ws[i] = ;
for (i = ; i < n; ++i) ws[x[i]=r[i]]++;
for (i = ; i < m; ++i) ws[i] += ws[i-];
for (i = n-; i >= ; --i) sa[--ws[x[i]]] = i;
for (j = , p = ; p < n; j *= , m = p)
{
for (p = , i = n - j; i < n; ++i) y[p++] = i;
for (i = ; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
for (i = ; i < n; ++i) wv[i] = x[y[i]];
for (i = ; i < m; ++i) ws[i] = ;
for (i = ; i < n; ++i) ws[wv[i]]++;
for (i = ; i < m; ++i) ws[i] += ws[i-];
for (i = n-; i >= ; --i) sa[--ws[wv[i]]] = y[i];
for (std::swap(x, y), p = , x[sa[]] = , i = ; i < n; ++i)
x[sa[i]] = cmp(y, sa[i-], sa[i], j) ? p- : p++;
}
} void calheight(int r[], int sa[], int n)
{
int i, j, k = ;
for (i = ; i <= n; ++i) rank[sa[i]] = i;
for (i = ; i < n; height[rank[i++]] = k)
for (k?k--:, j = sa[rank[i]-]; r[i+k] == r[j+k]; k++);
}
struct RMQ
{
int log2[N],mi[N][];
void init(int n)
{
for(int i = ; i <= n; i ++)log2[i] = (i == ? - : log2[i >> ] + );
for(int j = ; j < log2[n]; j ++)
for(int i = ; i + ( << j) <= n + ; i ++)
mi[i][j] = std::min(mi[i][j - ], mi[i + ( << j - )][j - ]);
}
int query(int ql, int qr)
{
int k = log2[qr - ql + ];
return std::min(mi[ql][k], mi[qr - ( << k) + ][k]);
}
} rmq;
int sc(int i,int k,int len)
{
if(k==) return len-sa[i];
return rmq.query(i+,i+k-);
}
int main()
{
int t,k;std::cin>>t;
while(t--)
{
int ans=;
scanf("%d%s",&k,ss);
int len=strlen(ss);
for(int i=;i<len;i++)
s[i]=ss[i]-'a'+;
s[len]=;
da(s,sa,len+,);
calheight(s,sa,len);
height[len+]=;
for(int i=;i<=len;i++)
rmq.mi[i][]=height[i];
rmq.init(len);
for(int i=;i<=len-k+;i++)
ans+=std::max(sc(i,k,len)-std::max(height[i],height[i+k]),);
printf("%d\n",ans);
}
return ;
}

hdu6194 string string string的更多相关文章

  1. [C#] string 与 String,大 S 与小 S 之间没有什么不可言说的秘密

    string 与 String,大 S 与小 S 之间没有什么不可言说的秘密 目录 小写 string 与大写 String 声明与初始化 string string 的不可变性 正则 string ...

  2. java.lang.String.getBytes(String charsetName)方法实例

    java.lang.String.getBytes(String charsetName) 方法编码将此String使用指定的字符集的字节序列,并将结果存储到一个新的字节数组. 声明 以下是java. ...

  3. Lua的string和string库总结

    Lua有7种数据类型,分别是nil.boolean.number.string.table.function.userdata.这里我总结一下Lua的string类型和string库,复习一下,以便加 ...

  4. C#,int转成string,string转成int

    转载:http://www.cnblogs.com/xshy3412/archive/2007/08/29/874362.html 1,int转成string用toString 或者Convert.t ...

  5. C#中对string与string[]的初步操作

    开篇之作,简单的对string与string[]进行初步操作,入门篇也,不多说,直接上代码. using System; using System.Collections.Generic; using ...

  6. Java提高篇——理解String 及 String.intern() 在实际中的应用

    1. 首先String不属于8种基本数据类型,String是一个对象.   因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. ...

  7. [C#]List<int>转string[],string[]转为string

    // List<int>转string[] public string[] ListInt2StringArray(List<int> input) { return Arra ...

  8. String和string的区别(C#)

    从位置讲: 1.String是.NET  Framework里面的String,小写的string是C#语言中的string 2.如果把using System;删掉,没有大写的String了,Sys ...

  9. String、String.valueOf、toString 它们三者的区别总结

    今天在使用这个的时候发现,他们三者好像在某些场所都是可以用的,但是不免会让人想到那既然它们三者这么的相似,那么总有些什么区别吧.我也在网上找了一些资料看.自己也看了API文档,就将他们三的区别总结一下 ...

  10. c++之string.find(string)

    先来看一个例子吧: #include "iostream" #include "string" using namespace std; // 定义函数求str ...

随机推荐

  1. hdu4734(记忆化搜索)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4734 思路:记忆化搜索. #include<iostream> #include<c ...

  2. 配置使用TargetFrameworks输出多版本类库

    1.类库右键 2.修改配置 修改前: <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <Targe ...

  3. Leetcode: Merge/Insert Interval

    题目 Given a collection of intervals, merge all overlapping intervals. For example,Given [1,3],[2,6],[ ...

  4. C语言基础之水仙花数

    题目:打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身. 例如:153是一个“水仙花数”,因为153=1的三次方+5的三次方+3的三次方. 程序分析:利用for循 ...

  5. Spring中bean的作用范围

    singleton作用域: Spring的scope的默认值是singleton Spring 只会为每一个bean创建一个实例,并保持bean的引用. <bean id="bean的 ...

  6. Linux下的高级拾色器—Pick

    导读 虽然大多数设计师都在使用 Mac,但也有一少部分在使用 Windows 甚至是 Linux 系统.在 Mac 和 Windows 中都有非常丰富的拾色器工具或插件可用,反而在开源界中这类颜色选择 ...

  7. Java Swing 日历 控件

    这是我改写的网上的DateChooser代码后的作品,使用效果如图所示.用法参考备注,以及Main函数中用法. /** * * Copyright: Ares. * All Rights Reserv ...

  8. 3.2 - FTP文件上传下载

    题目:开发一个支持多用户同时在线的FTP程序要求:1.用户加密认证2.允许同时多用户登录3.每个用户有自己的家目录,且只能访问自己的家目录4.对用户进行磁盘配额,每个用户的可用空间不同5.允许用户在f ...

  9. 三.插入和查找MySQL记录 数据类型

    1.插入数据的两种方式 1)INSERT tb1 VALUES('TOM',25,1863.25); 2)INSERT tb1(username,salary) VALUES('John',4500. ...

  10. mysql 正则表达式 regexp rlike not rlike

    regexp   rlike    not rlike 今天在上班的时候突然遇到了一个问题,C+组的同事要删除mysql里面的一些特殊数据,想要正则进行匹配.于是问我,没想到还真的把我难住了,问题如下 ...