Java 字符串操作|竞争编程
我有一个大小为N的字符串(小写字母),索引为1。Java 字符串操作|竞争编程,java,string,algorithm,data-structures,time-complexity,Java,String,Algorithm,Data Structures,Time Complexity,我有一个大小为N的字符串(小写字母),索引为1。 现在我得到了Q个查询,每个查询由两个整数x,y组成。 对于每个查询,我必须打印从子字符串(x,y)(包括x,y)删除的最小数量,以便子字符串具有相同频率的不同字符 例如:考虑一个形成子字符串abbCCD的查询, 现在它的最小删除数是2(1b,1c) 1这是我的解决方案,每个查询有O(26*26)个步骤。 制作一个累积频率数组来存储每个字符的频率,直到字符串中的“第i个”位置 dp[i][0]是从索引1到i(含索引1)的字符串中“a”的频率。 dp
现在我得到了Q个查询,每个查询由两个整数x,y组成。
对于每个查询,我必须打印从子字符串(x,y)(包括x,y)删除的最小数量,以便子字符串具有相同频率的不同字符
例如:考虑一个形成子字符串abbCCD的查询,
现在它的最小删除数是2(1b,1c)
dp[i][0]
是从索引1到i(含索引1)的字符串中“a”的频率。dp[i][1]
是从索引1到i(含索引1)的字符串中“b”的频率。以此类推,直到“z”为25 现在,在每个查询中,我们可以计算子字符串x到y中每个字符的频率,方法是从相同字符到y的频率减去字符“i”到“x-1”的频率,即
freq[i]=dp[x-1][i]-dp[y][i]代码>
现在,一旦我们得到子字符串中每个字符的频率,我们就可以迭代这些频率,并计算每个唯一字符的删除次数
例如,如果我们有一个子字符串“ddbbacc”
“a”的频率为1
“b”的频率为2
“c”的频率为2
“d”的频率为4
频率=[1,2,2,4]
在第一次迭代中,我们尝试使所有频率等于freq[0]
即1。
为此,我们从freq=2的字符中删除一个字符,从freq=4的字符中删除三个字符
这给了我们一个1+1+3=5
的答案
在第二次迭代中,我们试图使所有频率等于freq[1]
2.
为此,我们从具有freq=4
的字符中删除3个字符
我们还删除了freq<2
的所有字符
这给了我们一个1+2=3
的答案
在最坏的情况下,每个查询需要26*26
个步骤
import java.util.Arrays;
import java.util.Scanner;
import java.util.Collections;
import java.util.ArrayList;
class q1 {
static int[][] dp = new int[100005][27];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int q = in.nextInt();
in.nextLine();
String s = in.nextLine();
for (int i = 0; i < s.length(); i++){ //O(N*26)
for (int j = 0; j < 26; j++)
dp[i+1][j] = dp[i][j];
dp[i+1][(int)(s.charAt(i))-(int)('a')]++;
}
int x,y;
while(q>0){ //O(Q*700)
x = in.nextInt();
y = in.nextInt();
int freq[] = new int[27];
for(int i = 0; i < 26; i++) //O(1)
freq[i] = dp[y][i] - dp[x-1][i];
ArrayList<Integer> f = new ArrayList<Integer>();
for(int i = 0; i < 26; i++) //O(1)
if(freq[i] != 0)
f.add(freq[i]);
Collections.sort(f); //O(26*log26)
int ans = s.length() + 1;
int drop = 0;
for(int i = 0; i < f.size(); i++){ //O(26*26)
int currans = drop;
for(int j = i+1; j < f.size(); j++)
currans += (f.get(j)-f.get(i));
if (ans > currans)
ans = currans;
drop += f.get(i);
}
if (drop < ans)
ans = drop;
System.out.println(ans);
q--;
}
}
}
导入java.util.array;
导入java.util.Scanner;
导入java.util.Collections;
导入java.util.ArrayList;
q1类{
静态int[]dp=新int[100005][27];
公共静态void main(字符串[]args){
扫描仪输入=新扫描仪(系统输入);
int n=in.nextInt();
int q=in.nextInt();
in.nextLine();
字符串s=in.nextLine();
对于(inti=0;i0){//O(q*700)
x=in.nextInt();
y=in.nextInt();
int freq[]=新int[27];
for(inti=0;i<26;i++)/O(1)
频率[i]=dp[y][i]-dp[x-1][i];
ArrayList f=新的ArrayList();
for(inti=0;i<26;i++)/O(1)
如果(频率[i]!=0)
f、 添加(频率[i]);
Collections.sort(f);//O(26*log26)
int ans=s.长度()+1;
int-drop=0;
对于(inti=0;icurrans)
ans=咖喱;
下降+=f.get(i);
}
如果(下降
我的每个查询都是O(n),我们几乎有n个查询。总的来说是O(n2)。这种方法导致了TLE。这个问题似乎与Java无关。我更喜欢任何提供问题解决方案的人,都用Java提供,这样我就可以完全理解它。这就是标记。@weston我已经添加了代码。这是一个代码阻塞示例还是什么?我想看看原始拼图,如果你能链接到它?或者,如果没有,我在哪里可以获得样本数据来尝试它?
import java.util.Arrays;
import java.util.Scanner;
import java.util.Collections;
import java.util.ArrayList;
class q1 {
static int[][] dp = new int[100005][27];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int q = in.nextInt();
in.nextLine();
String s = in.nextLine();
for (int i = 0; i < s.length(); i++){ //O(N*26)
for (int j = 0; j < 26; j++)
dp[i+1][j] = dp[i][j];
dp[i+1][(int)(s.charAt(i))-(int)('a')]++;
}
int x,y;
while(q>0){ //O(Q*700)
x = in.nextInt();
y = in.nextInt();
int freq[] = new int[27];
for(int i = 0; i < 26; i++) //O(1)
freq[i] = dp[y][i] - dp[x-1][i];
ArrayList<Integer> f = new ArrayList<Integer>();
for(int i = 0; i < 26; i++) //O(1)
if(freq[i] != 0)
f.add(freq[i]);
Collections.sort(f); //O(26*log26)
int ans = s.length() + 1;
int drop = 0;
for(int i = 0; i < f.size(); i++){ //O(26*26)
int currans = drop;
for(int j = i+1; j < f.size(); j++)
currans += (f.get(j)-f.get(i));
if (ans > currans)
ans = currans;
drop += f.get(i);
}
if (drop < ans)
ans = drop;
System.out.println(ans);
q--;
}
}
}