Practice II 字符串

本来想做数论的……但是别的dalao都在做制胡窜

所以……

Chapter I KMP

KMP 最关键的不是这个半暴力的单模匹配

而是这个nxt数组 经常出一些奇怪的题 尤其是循环节可以直接由T-nxt[T]得到……神啊

总之记住nxt就是最长公共前后缀中前缀的尾指针就OK

T1 poj3461 Oulipo

Time cost: 10min

纯纯的板子 真没啥可说的

就是每次清空nxt就OK

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int N = 1000005;
 5 #define rep(i,a,n) for(int i = a;i <= n;i++)
 6 #define ms(a,b) memset(a,b,sizeof a)
 7
 8 char s[N],t[N];
 9 int S,T;
10 int nxt[N];
11 int ans;
12 void clr(){ms(nxt,0),ans = 0;}
13 void gnxt() {
14     int tmp = 0;
15     rep(i,2,T) {
16     while(tmp && t[tmp+1] != t[i]) tmp = nxt[tmp];
17     if(t[tmp+1] == t[i]) nxt[i] = ++tmp;
18     }
19 }
20 void KMP() {
21     int tmp = 0;
22     rep(i,1,S) {
23     while(tmp && t[tmp+1] != s[i]) tmp = nxt[tmp];
24     if(t[tmp+1] == s[i]) {
25         tmp++;
26         if(tmp == T) ans++;
27     }
28     }
29 }
30
31
32 int main() {
33     int q;
34     scanf("%d",&q);
35     while(q--) {
36     clr();
37     scanf("%s",t+1),scanf("%s",s+1);
38     S = strlen(s+1),T = strlen(t+1);
39     gnxt();
40     KMP();
41     printf("%d\n",ans);
42     }
43 }

T2 poj 2406 Power strings

Time cost:55min

之前曾经遇到过……最后暴力滚粗

今天算是靠着打表理解了

由于nxt定义的时候刨去了串本身是自己的最长公共前后缀

在最后一次求nxt的时候 我们考虑被nxt[T]抛弃的部分(记为len)

如果这一段能整除T,那么考虑第二段len长的串

它与第一段len长的串是相等的

同理可以推到T/len倍

同时 nxt取最大值 咕T-nxt[T]取最小

所以如果T是T-nxt[T]的整数倍 那么T-nxt[T]就是最小循环节

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int N = 1000005;
 5 #define rep(i,a,n) for(int i = a;i <= n;i++)
 6 #define ms(a,b) memset(a,b,sizeof a)
 7
 8 char s[N],t[N];
 9 int S,T;
10 int nxt[N];
11 int ans;
12 void clr(){ms(nxt,0),ans = 0;}
13 void gnxt() {
14     int tmp = 0;
15     rep(i,2,T) {
16     while(tmp && t[tmp+1] != t[i]) tmp = nxt[tmp];
17     if(t[tmp+1] == t[i]) nxt[i] = ++tmp;
18     }
19 }
20 void KMP() {
21     int tmp = 0;
22     rep(i,1,S) {
23     while(tmp && t[tmp+1] != s[i]) tmp = nxt[tmp];
24     if(t[tmp+1] == s[i]) {
25         tmp++;
26         if(tmp == T) ans++;
27     }
28     }
29 }
30
31
32 int main() {
33     while(1) {
34     clr();
35     scanf("%s",t+1);
36     T = strlen(t+1);
37     if(T == 1 && t[1] == ‘.‘) return 0;
38     gnxt();
39     if(T % (T - nxt[T]) == 0) printf("%d\n",T/(T-nxt[T]));
40     else puts("1");
41     }
42 }

T3 CF562D Om Nom and Necklace

Time cost:45min

有了前一道题做铺垫 还是比较容易想到的

交叉没法做 我们视AB为循环节

由于k给定 所以通过i和k可以求出一个循环节长度范围

如果这个长度是由nxt求出的最短循环节的整数倍就OK

实现的时候是 除len然后判断合法区间是否存在 这样就可以自动减掉后面剩的一段A

但是要注意 A或B为空的情况就是分成k段或者k+1段纯循环节(没有后缀) 可以特判

(实际A为空已经处理过了)

Code:

#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1000005;
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define ms(a,b) memset(a,b,sizeof a)

char s[N],t[N];
int S,T;
int nxt[N];
int ans;
void clr(){ms(nxt,0),ans = 0;}
void gnxt() {
    int tmp = 0;
    rep(i,2,T) {
    while(tmp && t[tmp+1] != t[i]) tmp = nxt[tmp];
    if(t[tmp+1] == t[i]) nxt[i] = ++tmp;
    }
}
void KMP() {
    int tmp = 0;
    rep(i,1,S) {
    while(tmp && t[tmp+1] != s[i]) tmp = nxt[tmp];
    if(t[tmp+1] == s[i]) {
        tmp++;
        if(tmp == T) ans++;
    }
    }
}
int n,k;

int main() {
    scanf("%d%d",&n,&k);
    scanf("%s",t+1);
    T = n;
    gnxt();
    rep(i,1,T) {
    int len = i - nxt[i];
    if(i % (k+1) == 0 && (i / (k+1)) % len == 0) putchar(‘1‘);//lenb==0
    else {
        //circular subsequence range
        int upp = i / k,down = i / (k + 1) + 1;
        upp = upp / len;
        down = (down + len - 1) / len;
        if(upp >= down) putchar(‘1‘);
        else putchar(‘0‘);
    }
    }
    puts("");
    return 0;
}

To be continued...

原文地址:https://www.cnblogs.com/yuyanjiaB/p/9765150.html

时间: 2024-08-11 19:25:58

Practice II 字符串的相关文章

1.1.2A+B for Input-Output Practice (II)

A+B for Input-Output Practice (II) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 25709 Accepted Submission(s): 16910 Problem Description Your task is to Calculate a + b. Input Input contains an 

梯度下降实用技巧II之学习率 Gradient descent in practice II -- learning rate

梯度下降实用技巧II之学习率 Gradient descent in practice II -- learning rate 梯度下降算法中的学习率(learning rate)很难确定,下面介绍一些寻找的实用技巧.首先看下如何确定你的梯度下降算法正在正常工作:一般是要画出代价函数 和迭代次数之间的图像,如下图所示.如果随着迭代次数的增加不断下降,那么说明梯度下降算法工作的很好,当到达一定迭代次数后基本持平时,说明已经收敛了,可以选取此时的作为参数.一般选取一个数小于,如果下降的幅度小于,则认

HDU-1090-A+B for Input-Output Practice (II)(骗访问量的)

A+B for Input-Output Practice (II) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 73325    Accepted Submission(s): 47653 Problem Description Your task is to Calculate a + b. Input Input contai

武汉科技大学ACM :1002: A+B for Input-Output Practice (II)

Problem Description Your task is to Calculate a + b. Input Input contains an integer N in the first line, and then N lines follow. Each line consists of a pair of integers a and b, separated by a space, one pair of integers per line. Output For each

SPOJ LCS2 - Longest Common Substring II 字符串 SAM

原文链接http://www.cnblogs.com/zhouzhendong/p/8982484.html 题目传送门 - SPOJ LCS2 题意 求若干$(若干<10)$个字符串的最长公共连续子串长度. 串长$\leq 100000$ 题解 建议在做本题之前,先去做SPOJ LCS,本题是其升级版. 题解链接 - SPOJ LCS - http://www.cnblogs.com/zhouzhendong/p/8982392.html 对于本题,我们只需要保持一下之后每一个串在第一个串的$

HDU 1090 A+B for Input-Output Practice (II)

Problem Description Your task is to Calculate a + b. Input Input contains an integer N in the first line, and then N lines follow. Each line consists of a pair of integers a and b, separated by a space, one pair of integers per line. Output For each

C题 - A+B for Input-Output Practice (II)

Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description Your task is to Calculate a + b. Input Input contains an integer N in the first line, and then N lines follow. Each line consists of a pair of integers a and b,

(HDU)1090 --A+B for Input-Output Practice (II)(输入输出练习(II))

#include <stdio.h> int main() { int m,n,t,i; scanf("%d",&t); for(i=1;i<=t;i++) { scanf("%d %d",&m,&n); printf("%d\n",m+n); } return 0; }

1002: A+B for Input-Output Practice (II)

问题描述: http://acm.wust.edu.cn/problem.php?id=1002&soj=0 代码实现: import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); int a, b, n; n = scan.nextInt(); while(n-- != 0){ a = scan.next