poj 1936 串(字序列匹配,满足贪心性质)复杂度O(n+m)

All in All
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 26071 Accepted: 10570

Description

You have devised a new encryption technique which encodes a message by inserting between its characters randomly generated strings in a clever way. Because of pending patent issues we will not discuss in detail how the strings are generated and inserted into the original message. To validate your method, however, it is necessary to write a program that checks if the message is really encoded in the final string.

Given two strings s and t, you have to decide whether s is a subsequence of t, i.e. if you can remove characters from t such that the concatenation of the remaining characters is s.

Input

The input contains several testcases. Each is specified by two strings s, t of alphanumeric ASCII characters separated by whitespace.The length of s and t will no more than 100000.

Output

For each test case output "Yes", if s is a subsequence of t,otherwise output "No".

Sample Input

sequence subsequence
person compression
VERDI vivaVittorioEmanueleReDiItalia
caseDoesMatter CaseDoesMatter

Sample Output

Yes
No
Yes
No

Source


水题。其实就是poj3267的一段子程序拿来又出了一道。

基本思想用贪心。

两个指针,i指向模式串,j指向母串。j一直往后扫,一旦发现与i指向的字符相同,i++。

这样当i走完模式串,也就说明模式串被匹配到了。

这里大家可能会困惑,如果有多个匹配,这样求得的是哪个匹配呢?

答案应该是,所有匹配到的字符 都尽可能排在前面的 那种情况。换句话说,只要匹配到了,i就可以++,无需考虑后面的。是满足贪心性质的。

这个与连续字串匹配是不同的:

例如:

在abzdabc中,如果需要匹配子序列abc,则会匹配到abzdabc.  只需要直接扫即可。并不需要kmp之类的优化。

而如果在abzdabc中,匹配子串abc,则只能匹配到abzdabc. 不具有贪心性质。暴力只能用o(n*m)复杂度,当然用kmp可以优化到O(n+m)。


这段子程序很经典,感受一下:

for (i = 0, j = 0; i < lens, j < lent; j++) {
    if (s[i] == t[j]) i++;
}
if (i == lens) cout << "Yes" << endl;
else cout << "No" << endl;


提交记录:

1.RE 。。。居然是因为数组开小了。人家是100000, 我开了10000

2.Accepted!

#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         #include 
        
          #include 
         
           #include 
          
            #include 
            #define MAX_V 500 #define oo 0x3f3f3f3f using namespace std; char s[100010], t[100010]; int main() { int i, j; while (cin >> s >> t) { int lens = strlen(s); int lent = strlen(t); for (i = 0, j = 0; i < lens, j < lent; j++) { if (s[i] == t[j]) i++; } if (i == lens) cout << "Yes" << endl; else cout << "No" << endl; } return 0; }  
           
          
         
       
      
      
     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java解决POJ3233—矩阵幂序列问题的代码和解释: ```java import java.util.Scanner; public class Main { static int n, k, m; static int[][] A, E; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); k = sc.nextInt(); m = sc.nextInt(); A = new int[n][n]; E = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { A[i][j] = sc.nextInt() % m; E[i][j] = (i == j) ? 1 : 0; } } int[][] res = matrixPow(A, k); int[][] ans = matrixAdd(res, E); printMatrix(ans); } // 矩阵乘法 public static int[][] matrixMul(int[][] a, int[][] b) { int[][] c = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < n; k++) { c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % m; } } } return c; } // 矩阵快速幂 public static int[][] matrixPow(int[][] a, int b) { int[][] res = E; while (b > 0) { if ((b & 1) == 1) { res = matrixMul(res, a); } a = matrixMul(a, a); b >>= 1; } return res; } // 矩阵加法 public static int[][] matrixAdd(int[][] a, int[][] b) { int[][] c = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { c[i][j] = (a[i][j] + b[i][j]) % m; } } return c; } // 输出矩阵 public static void printMatrix(int[][] a) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { System.out.print(a[i][j] + " "); } System.out.println(); } } } ``` 解释: 1. 首先读入输入的n、k、m和矩阵A,同时初始化单位矩阵E。 2. 然后调用matrixPow函数求出A的k次幂矩阵res。 3. 最后将res和E相加得到结果ans,并输出。 4. matrixMul函数实现矩阵乘法,matrixPow函数实现矩阵快速幂,matrixAdd函数实现矩阵加法,printMatrix函数实现输出矩阵。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值